//--------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include "TestDirectorLogin.h" #include "TestDirectorImport.h" #include "DataModule.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "AdvMemo" #pragma resource "*.dfm" TTestDirectorImportForm *TestDirectorImportForm; //--------------------------------------------------------------------------- static TestDirectorNodeList_t TestDirectorNodes; static TestDirectorNodeMap_t TestDirectorNodeMap; static TestDirectorNodeMap_t TestDirectorScenarioMap; //--------------------------------------------------------------------------- __fastcall TTestDirectorImportForm::TTestDirectorImportForm(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::FormClose(TObject *Sender, TCloseAction &Action) { TestDirectorConnection->Connected = false; } //--------------------------------------------------------------------------- const bool TTestDirectorImportForm::isTestCase( const AnsiString & description ) { const AnsiString code = description.SubString( 1, 3 ); return ( ( code == "STC" ) || ( code == "SDD" ) || ( code == "SRQ" ) ); } //--------------------------------------------------------------------------- void TTestDirectorImportForm::ShowForm( const AnsiString &project, int iteration ) { m_project = project; m_iteration = iteration; if (TestDirectorLoginForm->Login( TestDirectorConnection ) ) { ShowModal(); TestDirectorConnection->Connected = false; // Break Connection try { TestDirectorNodeList_t::iterator itr = TestDirectorNodes.begin(); while (itr != TestDirectorNodes.end()) { TestDirectorNode *td_node = (*itr); delete td_node; ++itr; } } catch(...) { } TestDirectorNodes.clear(); TestDirectorNodeMap.clear(); TestDirectorScenarioMap.clear(); } else { MessageDlg("Failed to connect to Test Director", mtError, TMsgDlgButtons() << mbOK, 0); } } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::LoadTestDataScenarioData(unsigned int &root_node, AnsiString &root_node_name) { TADOQuery *query = NULL; AnsiString sql_statement; try { query = new TADOQuery(this); query->Connection = TestDirectorConnection; // ----------------------------------------------------------------------- sql_statement = "SELECT AL_ITEM_ID,AL_FATHER_ID,AL_DESCRIPTION,AL_MEMO,AL_NO_OF_SONS " "FROM TD.ALL_LISTS " "ORDER BY TD.AL_DESCRIPTION"; query->SQL->Text = sql_statement; query->Open(); if (query->RecordCount > 0) { // int count_test_cases = query->RecordCount; while (!query->Eof) { unsigned short item_id = query->FieldByName("AL_ITEM_ID")->AsInteger; unsigned short father_id = query->FieldByName("AL_FATHER_ID")->AsInteger; TestDirectorNode *td_node = new TestDirectorNode; TestDirectorNodes.push_back(td_node); td_node->nodetype = TESTCASE; td_node->name = query->FieldByName("AL_DESCRIPTION")->AsString; td_node->parentnode = father_id; td_node->subjectnode = item_id; td_node->text1 = query->FieldByName("AL_MEMO")->AsString; // Pick out the SQT node for the moment - TODO revisit this if (td_node->name == "SQT") { root_node = item_id; root_node_name = td_node->name; } TestDirectorNodePair_t pair(item_id, td_node); TestDirectorNodeMap.insert( pair ); query->Next(); } // while // Build the Parent/Child linkages TestDirectorNodeMap_t::iterator itr = TestDirectorNodeMap.begin(); while (itr != TestDirectorNodeMap.end()) { TestDirectorNode *td_node = (*itr).second; TestDirectorNodeMap_t::iterator parent_itr = TestDirectorNodeMap.find( td_node->parentnode ); if (parent_itr != TestDirectorNodeMap.end()) { TestDirectorNode *parent_td_node = (*parent_itr).second; td_node->parent = parent_td_node; parent_td_node->children.push_back( td_node ); } ++itr; } // while } // ----------------------------------------------------------------------- } catch(...) { } delete query; } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::LoadTestScenarios(TestDirectorNode *parent_td_node) { TADOQuery *query = NULL; AnsiString sql_statement; try { query = new TADOQuery(this); query->Connection = TestDirectorConnection; // Load Test Scenarios sql_statement.sprintf("SELECT TS_TEST_ID,TS_SUBJECT,TS_NAME,TS_DESCRIPTION " "FROM TD.TEST " "WHERE TS_SUBJECT=%d " "ORDER BY TS_NAME", parent_td_node->subjectnode); query->SQL->Text = sql_statement; query->Open(); // int count_test_scenarios = query->RecordCount; while (!query->Eof) { AnsiString name = query->FieldByName("TS_NAME")->AsString; AnsiString description = query->FieldByName("TS_DESCRIPTION")->AsString; // unsigned int subject_id = query->FieldByName("TS_SUBJECT")->AsInteger; unsigned int test_id = query->FieldByName("TS_TEST_ID")->AsInteger; TestDirectorNode *td_node = new TestDirectorNode; TestDirectorNodes.push_back(td_node); td_node->nodetype = SCENARIO; td_node->name = name; td_node->subjectnode = test_id; td_node->text1 = description; TestDirectorNodePair_t pair(test_id, td_node); TestDirectorScenarioMap.insert( pair ); td_node->parent = parent_td_node; parent_td_node->children.push_back( td_node ); query->Next(); } // while query->Close(); } catch(...) { } delete query; } void __fastcall TTestDirectorImportForm::LoadTestSteps(TestDirectorNode *parent_td_node) { TADOQuery *query = NULL; AnsiString sql_statement; try { query = new TADOQuery(this); query->Connection = TestDirectorConnection; // Load the Test Scenario Steps sql_statement.sprintf("SELECT DS_TEST_ID,DS_STEP_NAME,DS_DESCRIPTION,DS_EXPECTED " "FROM TD.DESSTEPS " "WHERE DS_TEST_ID=%d " "ORDER BY DS_STEP_ORDER", parent_td_node->subjectnode ); query->SQL->Text = sql_statement; query->Open(); // int count_test_steps = query->RecordCount; while (!query->Eof) { int step_test_id = query->FieldByName("DS_TEST_ID")->AsInteger; AnsiString step_name = query->FieldByName("DS_STEP_NAME")->AsString; AnsiString step_description = query->FieldByName("DS_DESCRIPTION")->AsString; AnsiString step_expected = query->FieldByName("DS_EXPECTED")->AsString; TestDirectorNode *td_node = new TestDirectorNode; TestDirectorNodes.push_back(td_node); td_node->nodetype = TESTSTEP; td_node->name = step_name; td_node->subjectnode = step_test_id; td_node->text1 = step_description; td_node->text2 = step_expected; td_node->parent = parent_td_node; parent_td_node->test_steps.push_back( td_node ); query->Next(); } // while } catch(...) { } delete query; } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::FormShow(TObject *Sender) { TCursor Save_Cursor = Screen->Cursor; Screen->Cursor = crHourGlass; // Show hourglass cursor try { AnsiString root_node_name; unsigned int root_node = 0; LoadTestDataScenarioData(root_node, root_node_name); TTreeNode *node = NULL; TestCaseTreeView->Items->Clear(); node = TestCaseTreeView->Items->Add(NULL, root_node_name); node->ImageIndex = 0; node->SelectedIndex = 1; DrawSubTree(TestCaseTreeView, node, TESTCASE, root_node); // Start at the Subject Root } __finally { Screen->Cursor = Save_Cursor; // always restore the cursor } } //--------------------------------------------------------------------------- void TTestDirectorImportForm::DrawSubTree(TTreeView *tree, TTreeNode *node, int nodetype, int parent_id) { if (nodetype == TESTSTEP) { TestDirectorNodeMap_t::iterator itr = TestDirectorScenarioMap.find( parent_id ); if (itr != TestDirectorScenarioMap.end()) { TestDirectorNode *scenario_node = (*itr).second; DrawScenarioSteps(scenario_node); } } else { TestDirectorNodeMap_t::iterator itr = TestDirectorNodeMap.find( parent_id ); if (itr != TestDirectorNodeMap.end()) { if ((*itr).second->children.size() > 0) { TestDirectorNodeList_t::iterator child_itr = (*itr).second->children.begin(); while (child_itr != (*itr).second->children.end()) { TestDirectorNode *td_node = (*child_itr); if (td_node->nodetype == nodetype) { switch(td_node->nodetype) { case TESTCASE: { TTreeNode *subtree = tree->Items->AddChildObject(node, td_node->name, (TObject *)td_node); subtree->ImageIndex = 0; subtree->SelectedIndex = 1; DrawSubTree(tree, subtree, nodetype, td_node->subjectnode); } break; case SCENARIO: { /*TTreeNode *subtree =*/ tree->Items->AddChildObject(node, td_node->name, (TObject *)td_node); } break; } // switch } ++child_itr; } // for } } } } //--------------------------------------------------------------------------- void TTestDirectorImportForm::DrawScenarioSteps(TestDirectorNode *scenario_node) { TTreeNode *node = NULL; TestStepTreeView->Items->Clear(); node = TestStepTreeView->Items->Add(NULL, "Test Steps"); node->ImageIndex = 0; node->SelectedIndex = 1; TestDirectorNodeList_t::iterator itr = scenario_node->test_steps.begin(); while (itr != scenario_node->test_steps.end()) { TestDirectorNode *td_node = (*itr); /*TTreeNode *step_node = */TestStepTreeView->Items->AddChildObject(node, td_node->name, (TObject *)td_node); ++itr; } node->Expand(true); } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::TestCaseTreeViewChange( TObject *Sender, TTreeNode *Node) { TCursor Save_Cursor = Screen->Cursor; Screen->Cursor = crHourGlass; // Show hourglass cursor try { TestCaseMemo->Clear(); TestScenarioMemo->Clear(); TestDirectorNode *td_node = (TestDirectorNode *)(Node->Data); if (td_node != NULL) { TestScenarioPanel->Caption = td_node->name; TestCaseMemo->Lines->Text = td_node->text1; TestCaseMemo->WordWrap = wwRightMargin; TestCaseMemo->Update(); if (td_node->children.size() == 0) { LoadTestScenarios(td_node); } TTreeNode *node = NULL; TestScenarioTreeView->Items->Clear(); TestStepTreeView->Items->Clear(); node = TestScenarioTreeView->Items->Add(NULL, "Test Scenarios"); node->ImageIndex = 0; node->SelectedIndex = 1; DrawSubTree(TestScenarioTreeView, node, SCENARIO, td_node->subjectnode); node->Expand(true); } } __finally { Screen->Cursor = Save_Cursor; // always restore the cursor } } //--------------------------------------------------------------------------- AnsiString TTestDirectorImportForm::ProcessQuotedString(const AnsiString &source) { AnsiString result; const char *p = source.c_str(); for (int i=0; iCursor; Screen->Cursor = crHourGlass; // Show hourglass cursor try { query = new TADOQuery(this); query->Connection = Data_Module->IntegrationDBConnection; Data_Module->IntegrationDBConnection->BeginTrans(); for (unsigned i=0; iSelectionCount; i++) { TTreeNode *selected_node = TestCaseTreeView->Selections[i]; AnsiString current_text_case_level; ProcessSubtree(TestCaseTreeView, selected_node, query, current_text_case_level); } // Process Children TTreeNode *scenario_root_node = TestScenarioTreeView->TopItem; if (scenario_root_node != NULL) { AnsiString current_text_case_level; ProcessSubtree(TestScenarioTreeView, scenario_root_node, query, current_text_case_level); } if (Data_Module->IntegrationDBConnection->InTransaction) { Data_Module->IntegrationDBConnection->CommitTrans(); } } __finally { delete query; if (Data_Module->IntegrationDBConnection->InTransaction) { Data_Module->IntegrationDBConnection->RollbackTrans(); } Screen->Cursor = Save_Cursor; } } //--------------------------------------------------------------------------- void TTestDirectorImportForm::ProcessSubtree(TTreeView *treeview, TTreeNode *node, TADOQuery *query, AnsiString current_text_case_level) { ProcessTDNode(node, query, current_text_case_level); // Process Children TTreeNode *child_node = node->getFirstChild(); if (child_node != NULL) { do { ProcessSubtree(treeview, child_node, query, current_text_case_level); child_node = node->GetNextChild(child_node); } while (child_node != NULL); } } //--------------------------------------------------------------------------- void TTestDirectorImportForm::ProcessTDNode(TTreeNode *selected_node, TADOQuery *query, AnsiString ¤t_text_case_level) { AnsiString sql_statement; TestDirectorNode *td_node = (TestDirectorNode *)(selected_node->Data); if(td_node != NULL) { switch(td_node->nodetype) { case SUBJECT: // Do nothing break; case TESTCASE: { AnsiString usecase_id = td_node->name.SubString(1, td_node->name.Pos(" ")-1); if ( (!usecase_id.IsEmpty() && isTestCase( usecase_id )) || !current_text_case_level.IsEmpty() ) { AnsiString tc_name; if (!usecase_id.IsEmpty() && isTestCase( usecase_id )) { tc_name = td_node->name.SubString(td_node->name.Pos(" ")+1, td_node->name.Length()); current_text_case_level = usecase_id; sql_statement=""; sql_statement.sprintf("SELECT NAME, DESCRIPTION FROM TESTCASES " "WHERE USECASE_ID='%s'", usecase_id.c_str()); query->SQL->Text = sql_statement; query->Open(); if (query->RecordCount == 0) // Test Case not found .. Insert it { sql_statement=""; sql_statement.sprintf("INSERT INTO TESTCASES (USECASE_ID, NAME, TESTCASE_ID, DESCRIPTION) " "VALUES ('%s','%s','%s','%s')", usecase_id.c_str(), tc_name.c_str(), usecase_id.c_str(), ProcessQuotedString(td_node->text1).c_str() ); query->SQL->Text = sql_statement; query->ExecSQL(); } else { // Existing Test Case found .. Update it AnsiString desc = ProcessQuotedString(td_node->text1); if ( (query->FieldByName("NAME")->AsString != tc_name) || (query->FieldByName("DESCRIPTION")->AsString != desc) ) { sql_statement=""; sql_statement.sprintf("UPDATE TESTCASES SET NAME='%s',DESCRIPTION='%s' " "WHERE USECASE_ID='%s'", tc_name.c_str(), desc.c_str(), usecase_id.c_str() ); query->SQL->Text = sql_statement; query->ExecSQL(); } } } } } break; case SCENARIO: { TestDirectorNode *testcase_node = (TestDirectorNode *)(td_node->parent); TestDirectorNode *parent_testcase_node = (TestDirectorNode *)(td_node->parent->parent); AnsiString usecase_id = testcase_node->name.SubString(1, testcase_node->name.Pos(" ")-1); AnsiString parent_usecase_id = parent_testcase_node->name.SubString(1, parent_testcase_node->name.Pos(" ")-1); if ( (!usecase_id.IsEmpty() && isTestCase( usecase_id )) || (!parent_usecase_id.IsEmpty() && isTestCase( parent_usecase_id )) ) { AnsiString tc_id = td_node->name.SubString(1, td_node->name.Pos(" ")-1); AnsiString tc_name = td_node->name.SubString(td_node->name.Pos(" ")+1, td_node->name.Length()); current_text_case_level = tc_id; const char *p = tc_id.c_str(); AnsiString tc_scenario_seqno; // Skip to '.' while ( (*p != '.') && (*p != '\0') ) { p++; } if (*p == '.') { p++; while ( (*p != '.') && (*p != '\0') ) { tc_scenario_seqno += *p; p++; } } if ( (usecase_id.IsEmpty() || !isTestCase( usecase_id )) ) { usecase_id = parent_usecase_id; } // Do we already have a matching TEST_SCENARIOS (examine Project,Iteration,TestCase_ID and Name) ? sql_statement=""; sql_statement.sprintf("SELECT TESTCASE_SEQNO FROM TEST_SCENARIOS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND TESTCASE_ID='%s' AND NAME='%s'", m_project.c_str(), m_iteration, usecase_id.c_str(), tc_name.c_str()); query->SQL->Text = sql_statement; query->Open(); if (query->RecordCount == 0) // Scenario not found { int next_testcase_seqno = 0; if (tc_scenario_seqno.IsEmpty()) { sql_statement=""; sql_statement.sprintf("SELECT MAX(TESTCASE_SEQNO) MAX_SEQNO FROM TEST_SCENARIOS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND TESTCASE_ID='%s'", m_project.c_str(), m_iteration, usecase_id.c_str()); query->SQL->Text = sql_statement; query->Open(); next_testcase_seqno = query->FieldByName("MAX_SEQNO")->AsInteger; next_testcase_seqno++; } else { next_testcase_seqno = atoi(tc_scenario_seqno.c_str()); } sql_statement=""; sql_statement.sprintf("INSERT INTO TEST_SCENARIOS (PROJECT_CODE,ITERATION,TESTCASE_ID,USECASE,NAME,DESCRIPTION,TESTCASE_SEQNO) " "VALUES ('%s',%d,'%s','%s','%s','%s',%d)", m_project.c_str(), m_iteration, usecase_id.c_str(), usecase_id.c_str(), tc_name.c_str(), ProcessQuotedString(td_node->text1).c_str(), next_testcase_seqno); query->SQL->Text = sql_statement; query->ExecSQL(); } else { int next_testcase_seqno = 0; if (tc_scenario_seqno.IsEmpty()) { next_testcase_seqno = query->FieldByName("TESTCASE_SEQNO")->AsInteger; } else { next_testcase_seqno = atoi(tc_scenario_seqno.c_str()); } sql_statement=""; sql_statement.sprintf("UPDATE TEST_SCENARIOS SET DESCRIPTION='%s',TESTCASE_SEQNO=%d " "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND TESTCASE_ID='%s' AND NAME='%s'", ProcessQuotedString(td_node->text1).c_str(), next_testcase_seqno, m_project.c_str(), m_iteration, usecase_id.c_str(), tc_name.c_str()); query->SQL->Text = sql_statement; query->ExecSQL(); } } } break; case TESTSTEP: { TestDirectorNode *testcase_node = (TestDirectorNode *)(selected_node->Parent->Parent->Data); AnsiString usecase_id = testcase_node->name.SubString(1, testcase_node->name.Pos(" ")-1); TestDirectorNode *ts_node = (TestDirectorNode *)(selected_node->Parent->Data); if ( !usecase_id.IsEmpty() && isTestCase( usecase_id ) ) { AnsiString ts_name = ts_node->name.SubString(ts_node->name.Pos(" ")+1, ts_node->name.Length()); sql_statement=""; sql_statement.sprintf("SELECT TESTSCENARIO_NO FROM TEST_SCENARIOS " "WHERE PROJECT_CODE='%s' AND ITERATION=%d AND TESTCASE_ID='%s' AND NAME='%s'", m_project.c_str(), m_iteration, usecase_id.c_str(), ts_name.c_str()); query->SQL->Text = sql_statement; query->Open(); if (query->RecordCount == 1) { int testscenario_no = query->FieldByName("TESTSCENARIO_NO")->AsInteger; sql_statement=""; sql_statement.sprintf("DELETE FROM TXNSPEC_STEPS WHERE TESTSCENARIO_NO=%d AND NAME='%s'", testscenario_no, td_node->name.c_str()); query->SQL->Text = sql_statement; query->ExecSQL(); sql_statement=""; sql_statement.sprintf("INSERT INTO TXNSPEC_STEPS (TESTSCENARIO_NO,NAME,DESCRIPTION,EXPECTED_RESULT) " "VALUES (%d,'%s','%s','%s')", testscenario_no, td_node->name.c_str(), ProcessQuotedString(td_node->text1).c_str(), ProcessQuotedString(td_node->text2).c_str() ); query->SQL->Text = sql_statement; query->ExecSQL(); } } } break; } // switch } } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::TestScenarioTreeViewChange( TObject *Sender, TTreeNode *Node) { TCursor Save_Cursor = Screen->Cursor; Screen->Cursor = crHourGlass; // Show hourglass cursor try { TestStepMemo->Clear(); TestStepOutcomeMemo->Clear(); TestScenarioMemo->Clear(); TestDirectorNode *td_node = (TestDirectorNode *)(Node->Data); if (td_node != NULL) { TestStepPanel->Caption = td_node->name; TestScenarioMemo->Lines->Text = td_node->text1; TestScenarioMemo->WordWrap = wwRightMargin; TestScenarioMemo->Update(); if (td_node->test_steps.size() == 0) { LoadTestSteps(td_node); } TTreeNode *node = NULL; TestStepTreeView->Items->Clear(); node = TestStepTreeView->Items->Add(NULL, "Test Steps"); node->ImageIndex = 0; node->SelectedIndex = 1; DrawSubTree(TestStepTreeView, node, TESTSTEP, td_node->subjectnode); node->Expand(true); } } __finally { Screen->Cursor = Save_Cursor; // always restore the cursor } } //--------------------------------------------------------------------------- void __fastcall TTestDirectorImportForm::TestStepTreeViewChange( TObject *Sender, TTreeNode *Node) { TCursor Save_Cursor = Screen->Cursor; Screen->Cursor = crHourGlass; // Show hourglass cursor try { TestStepMemo->Clear(); TestStepOutcomeMemo->Clear(); TestDirectorNode *td_node = (TestDirectorNode *)(Node->Data); if (td_node != NULL) { TestStepMemo->Lines->Text = td_node->text1; TestStepMemo->WordWrap = wwRightMargin; TestStepMemo->Update(); TestStepOutcomeMemo->Lines->Text = td_node->text2; TestStepOutcomeMemo->WordWrap = wwRightMargin; TestStepOutcomeMemo->Update(); } } __finally { Screen->Cursor = Save_Cursor; // always restore the cursor } } //---------------------------------------------------------------------------