1
// TestRunnerDlg.cpp : implementation file
6
#include "TestRunnerApp.h"
7
#include "TestRunnerDlg.h"
9
#include "ActiveTest.h"
10
#include "ProgressBar.h"
11
#include "TreeHierarchyDlg.h"
12
#include "ListCtrlFormatter.h"
13
#include "ListCtrlSetter.h"
14
#include "MfcSynchronizationObject.h"
15
#include "ResourceLoaders.h"
16
#include <cppunit/TestFailure.h>
21
static char THIS_FILE[] = __FILE__;
25
- code duplication between OnOK() and OnQuitApplication()
26
- the threading need to be rewrite, so that GUI update occures in the original
27
thread, not in the thread that is running the tests. This slow down the time
28
needed to run the test much...
32
/////////////////////////////////////////////////////////////////////////////
33
// TestRunnerDlg dialog
35
const CString TestRunnerDlg::ms_cppunitKey( "CppUnit" );
38
TestRunnerDlg::TestRunnerDlg( TestRunnerModel *model,
39
int nDialogResourceId,
41
: cdxCDynamicDialog( nDialogResourceId, pParent )
43
ASSERT(0); // this constructor should not be used because of possible resource problems
44
// => use the constructor with the string parameter
48
TestRunnerDlg::TestRunnerDlg( TestRunnerModel *model,
49
const TCHAR* szDialogResourceId,
51
: cdxCDynamicDialog( szDialogResourceId == NULL ?
52
_T("CPP_UNIT_TEST_RUNNER_IDD_DIALOG_TESTRUNNER")
60
TestRunnerDlg::init(TestRunnerModel *model)
64
//{{AFX_DATA_INIT(TestRunnerDlg)
65
m_bAutorunAtStartup = FALSE;
70
m_bAutorunAtStartup = true;
73
ModifyFlags( flSWPCopyBits, 0 ); // anti-flickering option for resizing
77
TestRunnerDlg::DoDataExchange(CDataExchange* pDX)
79
cdxCDynamicDialog::DoDataExchange(pDX);
80
//{{AFX_DATA_MAP(TestRunnerDlg)
81
DDX_Control(pDX, IDC_DETAILS, m_details);
82
DDX_Control(pDX, IDC_LIST, m_listCtrl);
83
DDX_Control(pDX, IDOK, m_buttonClose);
84
DDX_Control(pDX, ID_STOP, m_buttonStop);
85
DDX_Control(pDX, ID_RUN, m_buttonRun);
86
DDX_Control(pDX, IDC_BROWSE_TEST, m_buttonBrowse);
87
DDX_Check(pDX, IDC_CHECK_AUTORUN, m_bAutorunAtStartup);
92
BEGIN_MESSAGE_MAP(TestRunnerDlg, cdxCDynamicDialog)
93
//{{AFX_MSG_MAP(TestRunnerDlg)
94
ON_BN_CLICKED(ID_RUN, OnRun)
95
ON_BN_CLICKED(ID_STOP, OnStop)
96
ON_BN_CLICKED(IDC_BROWSE_TEST, OnBrowseTest)
97
ON_COMMAND(ID_QUIT_APPLICATION, OnQuitApplication)
100
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, OnSelectedFailureChange)
101
ON_CBN_SELCHANGE(IDC_COMBO_TEST, OnSelectTestInHistoryCombo)
105
/////////////////////////////////////////////////////////////////////////////
106
// TestRunnerDlg message handlers
109
TestRunnerDlg::OnInitDialog()
111
cdxCDynamicDialog::OnInitDialog();
113
#ifdef CPPUNIT_SUBCLASSING_TESTRUNNERDLG_BUILD
114
m_hAccelerator = ::LoadAccelerators( AfxGetResourceHandle(),
116
m_hAccelerator = ::LoadAccelerators( g_testRunnerResource,
118
MAKEINTRESOURCE( IDR_ACCELERATOR_TEST_RUNNER ) );
119
// It always fails!!! I don't understand why. Complain about not finding the resource name!
120
ASSERT( m_hAccelerator !=NULL );
122
CComboBox *comboBox = (CComboBox *)GetDlgItem (IDC_COMBO_TEST);
126
VERIFY( m_errorListBitmap.Create( _T("CPP_UNIT_TEST_RUNNER_IDB_ERROR_TYPE"),
128
RGB( 255,0,255 ) ) );
130
m_testsProgress = new ProgressBar();
131
m_testsProgress->Create( NULL, NULL, WS_CHILD, CRect(), this, 0 );
132
m_testsProgress->ShowWindow( SW_SHOW );
133
m_testsProgress->MoveWindow( getItemClientRect( IDC_STATIC_PROGRESS_BAR ) );
137
initializeFixedSizeFont();
138
m_details.SetFont( &m_fixedSizeFont ); // Does not work. Need to investigate...
140
m_listCtrl.SetImageList( &m_errorListBitmap, LVSIL_SMALL );
141
m_listCtrl.SetExtendedStyle( m_listCtrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT );
143
int total_col_1_4 = m_settings.col_1 + m_settings.col_2 +
144
m_settings.col_3 + m_settings.col_4;
147
m_listCtrl.GetClientRect(&listBounds);
148
int col_5_width = listBounds.Width() - total_col_1_4; // 5th column = rest of listview space
149
ListCtrlFormatter formatter( m_listCtrl );
150
formatter.AddColumn( loadCString(IDS_ERRORLIST_TYPE), m_settings.col_1, LVCFMT_LEFT, 0 );
151
formatter.AddColumn( loadCString(IDS_ERRORLIST_NAME), m_settings.col_2, LVCFMT_LEFT, 1 );
152
formatter.AddColumn( loadCString(IDS_ERRORLIST_FAILED_CONDITION), m_settings.col_3, LVCFMT_LEFT, 2 );
153
m_listCtrl.setLineNumberSubItem( formatter.GetNextColumnIndex() );
154
formatter.AddColumn( loadCString(IDS_ERRORLIST_LINE_NUMBER), m_settings.col_4, LVCFMT_LEFT, 3 );
155
m_listCtrl.setFileNameSubItem( formatter.GetNextColumnIndex() );
156
formatter.AddColumn( loadCString(IDS_ERRORLIST_FILE_NAME), col_5_width, LVCFMT_LEFT, 4 );
159
updateHistoryCombo();
162
updateListColumnSize();
164
m_buttonRun.SetFocus();
166
if ( m_bAutorunAtStartup )
169
return FALSE; // return TRUE unless you set the focus to a control
170
// EXCEPTION: OCX Property Pages should return FALSE
174
TestRunnerDlg::~TestRunnerDlg()
177
delete m_testsProgress;
182
TestRunnerDlg::OnRun()
187
m_selectedTest = m_model->selectedTest();
189
if ( m_selectedTest == 0 )
197
int numberOfTests = m_selectedTest->countTestCases();
199
m_testsProgress->start( numberOfTests );
202
m_result = new CPPUNIT_NS::TestResultCollector( new MfcSynchronizationObject() );
203
m_testObserver = new CPPUNIT_NS::TestResult( new MfcSynchronizationObject() );
204
m_testObserver->addListener( m_result );
205
m_testObserver->addListener( this );
206
m_activeTest = new ActiveTest( m_selectedTest );
208
m_testStartTime = timeGetTime();
210
m_activeTest->run( m_testObserver );
212
m_testEndTime = timeGetTime();
217
TestRunnerDlg::addListEntry( const CPPUNIT_NS::TestFailure &failure )
219
CListCtrl *listCtrl = (CListCtrl *)GetDlgItem (IDC_LIST);
220
int currentEntry = m_result->testErrors() +
221
m_result->testFailures() -1;
223
ErrorTypeBitmaps errorType;
224
if ( failure.isError() )
225
errorType = errorTypeError;
227
errorType = errorTypeFailure;
229
ListCtrlSetter setter( *listCtrl );
230
setter.insertLine( currentEntry );
231
setter.addSubItem( failure.isError() ? _T("Error") : _T("Failure"), errorType );
234
setter.addSubItem( failure.failedTestName().c_str(), errorType );
236
// Set the asserted text
237
CString message( failure.thrownException()->message().shortDescription().c_str() );
238
message.Replace( '\n', ' ' ); // should only print the short description there,
239
setter.addSubItem( message ); // and dump the detail on an edit control when clicked.
241
// Set the line number
242
if ( failure.sourceLine().isValid() )
245
lineNumber.Format( _T("%ld"), failure.sourceLine().lineNumber() );
246
setter.addSubItem( lineNumber );
249
setter.addSubItem( _T("") );
252
setter.addSubItem( failure.sourceLine().fileName().c_str() );
254
if ( !listCtrl->GetFirstSelectedItemPosition() )
256
// Select first entry => display details of first entry.
257
listCtrl->SetItemState( currentEntry, LVIS_SELECTED, LVIS_SELECTED );
258
listCtrl->SetFocus(); // Does not work ?!?
261
listCtrl->RedrawItems( currentEntry, currentEntry );
262
listCtrl->UpdateWindow();
267
TestRunnerDlg::startTest( CPPUNIT_NS::Test *test )
269
CWnd *runningTestCaseLabel = GetDlgItem(IDC_RUNNING_TEST_CASE_LABEL);
270
if ( runningTestCaseLabel )
271
runningTestCaseLabel->SetWindowText( CString( test->getName().c_str() ) );
276
TestRunnerDlg::addFailure( const CPPUNIT_NS::TestFailure &failure )
278
addListEntry( failure );
279
if ( failure.isError() )
284
updateCountsDisplay();
289
TestRunnerDlg::endTest( CPPUNIT_NS::Test *test )
291
if ( m_selectedTest == 0 )
295
updateCountsDisplay();
296
m_testsProgress->step( m_failures == 0 && m_errors == 0 );
298
m_testEndTime = timeGetTime();
300
updateCountsDisplay();
302
if ( m_testsRun >= m_selectedTest->countTestCases() )
308
TestRunnerDlg::beRunning()
311
m_buttonRun.EnableWindow( FALSE );
312
m_buttonClose.EnableWindow( FALSE );
313
m_buttonBrowse.EnableWindow( FALSE );
315
// m_buttonRun.SetButtonStyle( m_buttonRun.GetButtonStyle() & ~BS_DEFPUSHBUTTON );
316
// m_buttonStop.SetButtonStyle( m_buttonStop.GetButtonStyle() | BS_DEFPUSHBUTTON );
321
TestRunnerDlg::beIdle()
323
m_bIsRunning = false;
324
m_buttonRun.EnableWindow( TRUE );
325
m_buttonBrowse.EnableWindow( TRUE );
326
m_buttonClose.EnableWindow( TRUE );
328
m_buttonRun.SetButtonStyle( m_buttonRun.GetButtonStyle() | BS_DEFPUSHBUTTON );
329
// m_buttonStop.SetButtonStyle( m_buttonStop.GetButtonStyle() & ~BS_DEFPUSHBUTTON );
334
TestRunnerDlg::beRunDisabled()
336
m_bIsRunning = false;
337
m_buttonRun.EnableWindow( FALSE );
338
m_buttonBrowse.EnableWindow( FALSE );
339
m_buttonStop.EnableWindow( FALSE );
340
m_buttonClose.EnableWindow( TRUE );
342
// m_buttonRun.SetButtonStyle( m_buttonRun.GetButtonStyle() | BS_DEFPUSHBUTTON );
343
// m_buttonStop.SetButtonStyle( m_buttonStop.GetButtonStyle() & ~BS_DEFPUSHBUTTON );
348
TestRunnerDlg::freeState()
352
delete m_testObserver;
357
TestRunnerDlg::reset()
362
m_testEndTime = m_testStartTime;
364
updateCountsDisplay();
368
m_testObserver = NULL;
370
CListCtrl *listCtrl = (CListCtrl *)GetDlgItem (IDC_LIST);
372
listCtrl->DeleteAllItems();
373
m_testsProgress->reset();
374
displayFailureDetailsFor( -1 );
379
TestRunnerDlg::updateCountsDisplay()
381
CStatic *statTestsRun = (CStatic *)GetDlgItem( IDC_STATIC_RUNS );
382
CStatic *statErrors = (CStatic *)GetDlgItem( IDC_STATIC_ERRORS );
383
CStatic *statFailures = (CStatic *)GetDlgItem( IDC_STATIC_FAILURES );
384
CEdit *editTime = (CEdit *)GetDlgItem( IDC_EDIT_TIME );
386
CString argumentString;
388
argumentString.Format( _T("%d"), m_testsRun );
389
statTestsRun->SetWindowText (argumentString);
391
argumentString.Format( _T("%d"), m_errors );
392
statErrors->SetWindowText( argumentString );
394
argumentString.Format( _T("%d"), m_failures );
395
statFailures->SetWindowText( argumentString );
397
argumentString.Format( _T("Execution time: %3.3lf seconds"),
398
(m_testEndTime - m_testStartTime) / 1000.0 );
399
editTime->SetWindowText( argumentString );
404
TestRunnerDlg::OnStop()
406
if ( m_testObserver )
407
m_testObserver->stop ();
414
TestRunnerDlg::OnOK()
416
if ( m_testObserver )
417
m_testObserver->stop ();
422
cdxCDynamicDialog::OnOK ();
427
TestRunnerDlg::OnSelectTestInHistoryCombo()
429
unsigned int currentSelection = getHistoryCombo()->GetCurSel ();
431
if ( currentSelection >= 0 &&
432
currentSelection < m_model->history().size() )
434
CPPUNIT_NS::Test *selectedTest = m_model->history()[currentSelection];
435
m_model->selectHistoryTest( selectedTest );
436
updateHistoryCombo();
445
TestRunnerDlg::updateHistoryCombo()
447
getHistoryCombo()->LockWindowUpdate();
449
getHistoryCombo()->ResetContent();
451
const TestRunnerModel::History &history = m_model->history();
452
for ( TestRunnerModel::History::const_iterator it = history.begin();
456
CPPUNIT_NS::Test *test = *it;
457
getHistoryCombo()->AddString( CString(test->getName().c_str()) );
460
if ( history.size() > 0 )
462
getHistoryCombo()->SetCurSel( 0 );
468
m_buttonBrowse.EnableWindow( TRUE );
471
getHistoryCombo()->UnlockWindowUpdate();
476
TestRunnerDlg::OnBrowseTest()
478
TreeHierarchyDlg dlg;
479
dlg.setRootTest( m_model->rootTest() );
480
if ( dlg.DoModal() == IDOK )
482
m_model->selectHistoryTest( dlg.getSelectedTest() );
483
updateHistoryCombo();
489
TestRunnerDlg::PreTranslateMessage(MSG* pMsg)
491
if ( ::TranslateAccelerator( m_hWnd,
497
return cdxCDynamicDialog::PreTranslateMessage(pMsg);
502
TestRunnerDlg::getHistoryCombo()
504
CComboBox *comboBox = (CComboBox *)GetDlgItem (IDC_COMBO_TEST);
511
TestRunnerDlg::loadSettings()
513
m_model->loadSettings(m_settings);
514
RestoreWindowPosition( TestRunnerModel::settingKey,
515
TestRunnerModel::settingMainDialogKey );
518
m_bAutorunAtStartup = m_settings.autorunOnLaunch;
523
TestRunnerDlg::saveSettings()
525
m_settings.autorunOnLaunch = ( m_bAutorunAtStartup != 0 );
526
StoreWindowPosition( TestRunnerModel::settingKey,
527
TestRunnerModel::settingMainDialogKey );
529
m_settings.col_1 = m_listCtrl.GetColumnWidth(0);
530
m_settings.col_2 = m_listCtrl.GetColumnWidth(1);
531
m_settings.col_3 = m_listCtrl.GetColumnWidth(2);
532
m_settings.col_4 = m_listCtrl.GetColumnWidth(3);
534
m_model->saveSettings(m_settings);
539
TestRunnerDlg::OnQuitApplication()
541
if ( m_testObserver )
542
m_testObserver->stop();
547
CWinApp *app = AfxGetApp();
548
ASSERT( app != NULL );
549
app->PostThreadMessage( WM_QUIT, 0, 0 );
554
TestRunnerDlg::model()
556
ASSERT( m_model != NULL );
562
TestRunnerDlg::OnClose()
569
TestRunnerDlg::getItemWindowRect( unsigned int itemId )
571
CWnd * pItem = GetDlgItem( itemId );
574
pItem->GetWindowRect( &rect );
580
TestRunnerDlg::getItemClientRect( unsigned int itemId )
582
CRect rect = getItemWindowRect( itemId );
583
if ( !rect.IsRectNull() )
585
CPoint clientTopLeft = rect.TopLeft();
586
ScreenToClient( &clientTopLeft );
587
rect = CRect( clientTopLeft, rect.Size() );
595
TestRunnerDlg::initializeLayout()
597
// see DynamicWindow/doc for documentation
598
const int listGrowthRatio = 30;
599
AddSzXControl( IDC_COMBO_TEST, mdResize );
600
AddSzXControl( IDC_BROWSE_TEST, mdRepos );
601
AddSzXControl( IDC_RUNNING_TEST_CASE_LABEL, mdResize );
602
AddSzXControl( ID_RUN, mdRepos );
603
AddSzXControl( *m_testsProgress, mdResize );
604
AddSzXControl( IDC_CHECK_AUTORUN, mdRepos );
605
AddSzControl( IDC_LIST, 0, 0, 100, listGrowthRatio );
606
AddSzXControl( ID_STOP, mdRepos );
607
AddSzXControl( IDOK, mdRepos );
608
AddSzYControl( IDC_STATIC_DETAILS, listGrowthRatio, listGrowthRatio );
609
AddSzControl( IDC_DETAILS, 0, listGrowthRatio, 100, 100 );
610
AddSzControl( IDC_EDIT_TIME, mdResize, mdRepos );
615
TestRunnerDlg::OnSize( UINT nType, int cx, int cy )
617
cdxCDynamicDialog::OnSize(nType, cx, cy);
618
updateListColumnSize();
623
TestRunnerDlg::updateListColumnSize()
625
if ( !m_listCtrl.GetSafeHwnd() )
628
// resize to fit last column
629
CRect listBounds = getItemClientRect( IDC_LIST );
632
for (int i = 0; i < 4; ++i)
633
width_1_4 += m_listCtrl.GetColumnWidth( i );
635
// the 4 offset is so no horiz scroll bar will appear
636
m_listCtrl.SetColumnWidth(4, listBounds.Width() - width_1_4 - 4);
641
TestRunnerDlg::OnSelectedFailureChange( NMHDR* pNMHDR,
644
NM_LISTVIEW *pNMListView = (NM_LISTVIEW*)pNMHDR;
646
if ( (pNMListView->uNewState & LVIS_SELECTED) != 0 ) // item selected
647
displayFailureDetailsFor( pNMListView->iItem );
654
TestRunnerDlg::displayFailureDetailsFor( unsigned int failureIndex )
657
if ( m_result && failureIndex < m_result->failures().size() )
658
details = m_result->failures()[ failureIndex ]->thrownException()->what();
660
details.Replace( _T("\n"), _T("\r\n") );
662
m_details.SetWindowText( details );
667
TestRunnerDlg::initializeFixedSizeFont()
670
GetFont()->GetLogFont( &font );
671
font.lfPitchAndFamily = FIXED_PITCH | //VARIABLE_PITCH
672
(font.lfPitchAndFamily & ~15); // font family
673
m_fixedSizeFont.CreateFontIndirect( &font );