E D R , A S I H C RSS

Gui Testing With Mfc

CppUnit 을 이용한 MFC 에서의 GuiTesting (시도중. 결과는?)

Dialog Based 에서의 테스트

Dialog Based 의 경우 Modal Dialog 를 이용하게 된다. 이 경우 Dialog 내에서만 메세지루프가 작동하게 되므로, DoModal 함수로 다이얼로그를 띄운 이후의 코드는 해당 Dialog 가 닫히기 전까지는 실행되지 않는다. 고로, CppUnit 에서의 fixture 를 미리 구성하여 쓸 수 없다.

그래서, 테스트를 시도할때 Modaless Dialog 로 만들고 실험을 하였다.


원하는 작동 모습은 이렇다.
  1. Editbox 에 아무 글을 넣고
  2. Add 버튼을 누르면
  3. List box 에 Editbox 에 쓴 글이 순서대로 처음부터 채워지고
  4. List box 에서의 커서는 채워진 글에 위치한다.
  5. List box 에 값이 채워지고 난 뒤, Editbox 의 글은 지워진다.

1. GUI Runner Setting

이는 App 클래스의 InitInstance 함수에서 해준다.

~cpp 
#include "stdafx.h"
#include "GuiTestingOne.h"
#include "GuiTestingOneDlg.h"

#include "cppunit\ui\mfc\TestRunner.h"

#include "GuiTestCase.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

BEGIN_MESSAGE_MAP(CGuiTestingOneApp, CWinApp)
	//{{AFX_MSG_MAP(CGuiTestingOneApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG
	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()

CGuiTestingOneApp::CGuiTestingOneApp()
{
}

CGuiTestingOneApp theApp;

BOOL CGuiTestingOneApp::InitInstance()
{
	AfxEnableControlContainer();

	CppUnit::MfcUi::TestRunner runner;
	runner.addTest (GuiTestCase::suite());
	runner.run();

/* --- Test Runner 만 실행되도록, 다이얼로그 띄우는 부분을 일단 막아둔다. 마지막에 실행할때 이 부분의 주석처리 된 부분을 풀어주면 된다.
#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	CGuiTestingOneDlg dlg;
	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
	}
	else if (nResponse == IDCANCEL)
	{
	}
*/
	return FALSE;
}

2. Test Case 의 작성


1. 연습

일단, 제대로 작동하는지 알아보기 위해 연습겸 m_bFlag 변수를 만들어서 테스트를 했다.

테스트 통과시 예상되는 결과
test1One 연습겸 Assert Equals. 10 == 10
test2GuiOne 버튼이 눌러졌을 경우에 CGuiTestingOneDlg::m_bFlag 가 true 상태가 된다.

~cpp 
#include <cppunit/TestCase.h>
#include <cppunit/Extensions/HelperMacros.h>

#include "stdafx.h"                                  // resource, mfc 를 이용할 수 있다.
#include "GuiTestingOneDlg.h"                        // import GuiTestingOneDlg 

class GuiTestCase : public CppUnit::TestCase {
	CPPUNIT_TEST_SUITE(GuiTestCase);
	CPPUNIT_TEST ( test1One );
	CPPUNIT_TEST ( test2GuiOne );
	CPPUNIT_TEST ( test3ListAdd );
	CPPUNIT_TEST_SUITE_END();

public:
	CGuiTestingOneDlg* pDlg;
	void setUp () {
		pDlg = new CGuiTestingOneDlg();
		pDlg->Create(IDD_GUITESTINGONE_DIALOG);
	}

	void tearDown () {
		delete pDlg;
	}

public:
	void test1One () {
		CPPUNIT_ASSERT_EQUAL (10, 10);
	}

	void test2GuiOne () {

		pDlg->OnButtonadd();
		CPPUNIT_ASSERT_EQUAL (true, pDlg->m_bFlag);
	}
};

코드 추가
~cpp 
void CGuiTestingOneDlg::OnButtonadd() 
{
	// TODO: Add your control notification handler code here
	m_bFlag = true;
}

2. 텍스트 추가

테스트 통과시 예상되는 결과
test1One 연습겸 Assert Equals. 10 == 10
test2GuiOne 버튼이 눌러졌을 경우에 CGuiTestingOneDlg::m_bFlag 가 true 상태가 된다.
test3ListAdd Editbox 에 "Testing..." 을 셋팅. 버튼을 눌렀을 때 Listbox 의 item 갯수가 1개임을 확인
. Listbox 의 첫번째 item 의 스트링이 "Testing..." 임을 확인

~cpp 
	void test3ListAdd () {
		pDlg->m_ctlEdit.SetWindowText("Testing...");
		pDlg->OnButtonadd();
		CPPUNIT_ASSERT_EQUAL (1, pDlg->m_ctlList.GetCount());
		CString str;

		pDlg->m_ctlList.GetText(0, str);
		CPPUNIT_ASSERT ( isSameString(str, "Testing..."));
	}

	bool isSameString (CString& str1, PSTR str2) {
		return str1.Compare(str2) == 0;
	}
};

코드 추가
~cpp 
void CGuiTestingOneDlg::OnButtonadd() 
{
	// TODO: Add your control notification handler code here
	m_bFlag = true;
	CString str;
	m_ctlEdit.GetWindowText(str);
	m_ctlList.AddString(str);
}

3. more...

테스트 통과시 예상되는 결과
test1One 연습겸 Assert Equals. 10 == 10
test2GuiOne 버튼이 눌러졌을 경우에 CGuiTestingOneDlg::m_bFlag 가 true 상태가 된다.
test3ListAdd Editbox 에 "Testing..." 을 셋팅. 버튼을 눌렀을 때 Listbox 의 item 갯수가 1개임을 확인
. Listbox 의 첫번째 item 의 문자열이 "Testing..." 임을 확인
test4ListAddMore test3 에 추가된 형태. Editbox 에 다시 "Testing2..." 를 셋팅하고, 버튼을 눌렀을 때 Listbox 의 item 갯수가 2개임을 확인
. Listbox 의 두번째 item 의 문자열이 "Testing2..." 임을 확인

~cpp 
	void test4ListAddMore () {
		test3ListAdd();
		CString str;

		pDlg->m_ctlEdit.SetWindowText("Testing2...");
		pDlg->OnButtonadd();
		CPPUNIT_ASSERT_EQUAL (2, pDlg->m_ctlList.GetCount());
		pDlg->m_ctlList.GetText(1, str);
		CPPUNIT_ASSERT ( isSameString(str, "Testing2..."));
	}

4. 'List box 에서의 커서는 채워진 글에 위치한다' 에 대한 테스트

테스트 통과시 예상되는 결과
test1One 연습겸 Assert Equals. 10 == 10
test2GuiOne 버튼이 눌러졌을 경우에 CGuiTestingOneDlg::m_bFlag 가 true 상태가 된다.
test3ListAdd Editbox 에 "Testing..." 을 셋팅. 버튼을 눌렀을 때 Listbox 의 item 갯수가 1개임을 확인
. Listbox 의 첫번째 item 의 문자열이 "Testing..." 임을 확인
test4ListAddMore test3 에 추가된 형태. Editbox 에 다시 "Testing2..." 를 셋팅하고, 버튼을 눌렀을 때 Listbox 의 item 갯수가 2개임을 확인
. Listbox 의 두번째 item 의 문자열이 "Testing2..." 임을 확인
test5ListCursorOne test3 진행시 선택된 Item 이 0 번째 임을 확인
test6ListCursorTwo test4 진행시 선택된 Item 이 1 번째 임을 확인

~cpp 
	void test5ListCursorOne () {
		test3ListAdd();
		CPPUNIT_ASSERT_EQUAL(0, pDlg->m_ctlList.GetCurSel());
	}

	void test6ListCursorTwo () {
		test4ListAddMore();
		CPPUNIT_ASSERT_EQUAL(1, pDlg->m_ctlList.GetCurSel());
	}


코드 추가
~cpp 
void CGuiTestingOneDlg::OnButtonadd() 
{
	// TODO: Add your control notification handler code here
	CString str;
	m_ctlEdit.GetWindowText(str);
	m_ctlList.AddString(str);
	m_ctlList.SetCurSel(m_ctlList.GetCount()-1);
	m_bFlag = true;
}


5. edit box 의 내용이 데이터 추가후 초기화 되는지 확인

테스트 통과시 예상되는 결과
test1One 연습겸 Assert Equals. 10 == 10
test2GuiOne 버튼이 눌러졌을 경우에 CGuiTestingOneDlg::m_bFlag 가 true 상태가 된다.
test3ListAdd Editbox 에 "Testing..." 을 셋팅. 버튼을 눌렀을 때 Listbox 의 item 갯수가 1개임을 확인
. Listbox 의 첫번째 item 의 문자열이 "Testing..." 임을 확인
test4ListAddMore test3 에 추가된 형태. Editbox 에 다시 "Testing2..." 를 셋팅하고, 버튼을 눌렀을 때 Listbox 의 item 갯수가 2개임을 확인
. Listbox 의 두번째 item 의 문자열이 "Testing2..." 임을 확인
test5ListCursorOne test3 진행시 선택된 Item 이 0 번째 임을 확인
test6ListCursorTwo test4 진행시 선택된 Item 이 1 번째 임을 확인
test7EmptyEditbox test3 진행시 Editbox 의 스트링이 비었는지 확인

~cpp 
	void test7EmptyEditbox () {
		test3ListAdd();
		CString str;

		pDlg->m_ctlEdit.GetWindowText(str);
		CPPUNIT_ASSERT (str.IsEmpty());
	}

코드 추가
~cpp 
void CGuiTestingOneDlg::OnButtonadd() 
{
	// TODO: Add your control notification handler code here
	CString str;
	m_ctlEdit.GetWindowText(str);
	m_ctlList.AddString(str);
	m_ctlList.SetCurSel(m_ctlList.GetCount()-1);
	m_ctlEdit.SetWindowText("");
	m_bFlag = true;
}

여기까지로 생각해놓은 테스트들이 전부 완료. 앞에 InitInstance 에 써 넣은 주석을 풀고, 실제로 실행해보자.
~cpp 
BOOL CGuiTestingOneApp::InitInstance()
{
	AfxEnableControlContainer();

	CppUnit::MfcUi::TestRunner runner;
	runner.addTest (GuiTestCase::suite());
	runner.run();

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	CGuiTestingOneDlg dlg;
	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
	}
	else if (nResponse == IDCANCEL)
	{
	}

	return FALSE;
}


문제점

  • 모달리스 다이얼로그인 관계로, 테스트를 run 으로 실행할 때 마다 Dialog 가 켜졌다 꺼졌다 한다. 이에 따른 속도의 지연의 문제. -> CDialog::ShowWindow(SH_HIDE); 로 해결 가능


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:20
Processing time 0.0230 sec