What
is Extreme Programming?
Extreme Programming is a discipline of software development
based on values of simplicity,
communication, feedback, and courage.
It works by bringing the whole team together in the presence of
simple practices, with enough feedback to enable the team to see
where they are and to tune the practices to their unique situation.
Ron Jeffries 11/08/2001
test
The best XP teams treat their customer tests the same
way they do programmer tests: once the test runs, the team keeps
it running correctly thereafter. This means that the system only
improves, always notching forward, never backsliding.
Note: unit testing, function testing, stress testing
CppUnit - C++ port of JUnit
XUnit is a unit testing framework originally developed
by Kent Beck in the paper "Simple
Smalltalk Testing:With Patterns" and ported to many
platforms with the help of many independent groups.
CppUnit
download page: 1.6.2 src
doc 2001/10/20
JUnit
home page
CppUnit 在 VC++ 6.0 上的安裝與測試
步驟如下:
- 解壓縮
cppunit-1_6_2_tar.gz 到自己指定的資料夾內 (例如: vc98\cppunit162, 資料夾
vc98\ 為你的機器上 VC 安裝的資料夾, 解壓縮後包括 bin, include, lib, doc 等資料夾), 解壓縮
cppunit-docs-1_6_2_tar.gz 到 vc98\cppunit162\docs 內 (此為線上參考資料:
vc90\cppunit162\docs\index.html)
- 編譯 TestRunner 應用程式(具 Win32 GUI) (TestRunner??.dll), 及 CppUnit
與 DSPlugIn 類別函式庫 (CppUnit??.lib 與 TestRunnerDSPlugIn??.dll)
- 執行 Visual Studio, File/Open Workspace, 開啟 vc98\cppunit162\src\msvc6\testrunner\TestRunner.dsw
- 指定 TestRunner 為 Active project
- 視你的需要在 Build/Set Active Configuration... 選擇 Release, Debug
或是 Debug Crossplatform
- Build/Build TestRunner.dll 或是 Build/Build TestRunnerd.dll
或是 Build/Build TestRunnercd.dll
- 結果為 vc98\cppunit162\lib\TestRunner??.dll 及 TestRunner??.lib
- 由於 Project/Dependencies... 內的設定,在製作 TestRunner??.dll 之前會先編譯
cppunit 及 DSPlugIn 兩個 projects, 產生 CppUnit??.lib 及 TestRunnerDSPlugIn??.dll
- 測試 1:快速應用測試同時安裝 Visual Studio IDE 環境中的 add-ins
- 執行 Visual Studio, File/Open Workspace, 開啟 vc98\cppunit162\examples\examples.dsw
- 指定 HostApp 為 Active project
- Build/Set Active Configuration..., 選擇 Release, Debug 或是
Debug Crossplatform
- Build/Build HostApp.exe
- 安裝 Visual Studio IDE 環境中的 add-ins
- Tools/Customize.../Add-ins and macro files,
點選 Browse...
- 找到 vc98\cppunit162\lib\TestRunnerDSPlugIn??.dll
- 按下確定,安裝 add-ins (這個 Add-in 主要是讓 TestRunner GUI 程式在執行時可以直接在界面中點選
failure 或是 error 的那列原始程式並且在 Visual Studio IDE 環境中顯示以供編輯修改)
- Build/Execute HostApp.exe
- 執行 HostApp 時 HostApp 程式中執行下列程式碼:
TestRunner runner; runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest()
); runner.run();
)
此時 TestRunner GUI 界面視窗在螢幕上開啟,第一次執行時必須點選 Browse 按鈕來挑選要執行的測試,
(這些測試是在程式中藉由
CPPUNIT_TEST_SUITE( XXXXTest ); CPPUNIT_TEST( testRoutine1
); CPPUNIT_TEST( testRoutine2 ); CPPUNIT_TEST_SUITE_END();
及 CPPUNIT_TEST_SUITE_REGISTRATION( XXXXTest );
來登錄的),並且點選 Run 按鈕來執行測試,測試完成後按下 Close 按鈕可以開始執行正常的程式。
- 測試 2:完整測試 CppUnit 各個函式功能
- 執行 Visual Studio, File/Open Workspace, 開啟 vc98\cppunit162\examples\msvc6\CppUnitTestApp\CppUnitTestApp.dsw
- 指定 CppUnitTestApp 為 Active project
- Build/Set Active Configuration..., 選擇 Release, Debug 或是
Debug Crossplatform
- Build/Build CppUnitTestApp.exe
- Build/Execute CppUnitTestApp.exe
- 螢幕上會看到 TestRunner GUI, 開啟後自動會執行 All Tests, 在 ExceptionTest.cpp
line 103 有唯一的一個 failure
CppUnitTestApp 是一個 MFC 程式,裡面有所有 CppUnit 功能的測試,也是一個完整的範例程式
- 設定 Visual Studio 的 include directory 及 lib directory, 如此以後經由此
IDE 界面編譯的程式都可以順利地找到 CppUnit include 檔及函式庫
Tools/Options, Directories, Include Files 增加 vc98\cppunit162\include
及 vc98\cppunit162\include\msvc6,
Tools/Options, Directories, Library Files 增加 vc98\cppunit162\lib
這樣子可以省事一點,但是也使得 workspace/project 沒有辦法帶到其它機器上去工作。
參考文件:
vc98\cppunit162\INSTALL-WIN32.txt
使用 CppUnit 及 TestRunner
製作一個新的 Project 時如何使用 CppUnit 及 TestRunner
- 修改 Project/Settings
- 使用 RTTI: C/C++, C++ Language, 勾選 Enable Run-Time Type Information
(RTTI)
- 連結 CppUnit??.lib TestRunner??.lib: Project/Settings...,
Link, General, Object/Library Modules 設定 CppUnit??.lib TestRunner??.lib
- Project/Settings..., Pre-Link step 增加 Pre-Link Command:
copy d:\vc98\cppunit162\lib\TestRunner??.dll Debug (應用程式如果需要使用
WIN32 GUI,需要 new TestRunner 物件時,必須要能夠在執行檔相同的資料夾中找到 TestRunner??.dll)
- 應用程式可以決定要不要使用 TestRunner GUI 類別來觀看結果
不使用 TestRunner 類別時主要有三種方法:
- 需要測試函式的類別先繼承 CppUnit::TestCase 類別,然後 override runTest()
函式,在其中加上測試碼,例如:
--- ComplexNumberTest.h
--- #include #include "Complex.h"
using namespace std; using namespace CppUnit; class CComplexNumberTest
: public TestCase { public: CComplexNumberTest(string name)
: TestCase (name) {} protected: void setUp() { TRACE("setUp()\n");
} void runTest() { TRACE("runTest()\n"); CPPUNIT_ASSERT
(CComplex (10, 1) == CComplex (10, 1)); CPPUNIT_ASSERT (!(CComplex
(1, 1) == CComplex (2, 2))); } void tearDown() { TRACE("tearDown()\n");
} }; --- Complex.h --- class CComplex { public: friend bool
operator==(const CComplex& a, const CComplex& b);
public: CComplex(double r, double i = 0) : m_real(r), m_imaginary(i)
{} private: double m_real, m_imaginary; }; --- Complex.cpp
--- bool operator==(const CComplex& a, const CComplex&
b) { return (a.m_real == b.m_real) && (a.m_imaginary
== b.m_imaginary); } --- Method1View.cpp --- void CMethod1View::OnInitialUpdate()
{ CView::OnInitialUpdate(); CComplexNumberTest *tc = new
CComplexNumberTest("test name"); tc->run();
delete tc; }
測試結果上面這個方法會順序執行 setUp(), runTest(),
及 tearDown(), 但是 runTest() 中所有的 CPPUNIT_ASSERT() 並沒有作用????
而且執行過後記憶體有 memory leakage???
- CComplexNumberTest 類別中的所有資料設定我們稱為一個
fixture, 也就是一種測試資料的組合,我們在此類別中可以設計一些測試的成員函式 testXXXX(),它們基本上每一個都是獨立的,我們可以利用
TestCaller 類別來獨立測試每一個函式,每一個函式在測試前 TestCaller 都會產生新的 CComplexNumberTest
的物件,依序執行 ctor(), setUp(), testXXXX(), tearDown(), 及 dtor()
#include
#include ... class ComplexNumberTest
: public TestCase { private: Complex *m_10_1, *m_1_1, *m_11_2;
public: void setUp() { m_10_1 = new Complex(10, 1); m_1_1
= new Complex(1, 1); m_11_2 = new Complex(11, 2); } void
tearDown() { delete m_10_1, delete m_1_1, delete m_11_2;
} void testEquality() { CPPUNIT_ASSERT(*m_10_1 == *m_10_1);
CPPUNIT_ASSERT(!(*m_10_1 == *m_11_2)); } void testAddition()
{ CPPUNIT_ASSERT(*m_10_1 + *m_1_1 == *m_11_2); } }; ...
TestCaller test1("testEquality",
&ComplexNumberTest::testEquality); test1.run (); TestCaller
test2("testAddition", &ComplexNumberTest::testAddition);
test2.run ();
- 上面 TestCaller 物件可以藉由 TestSuite 物件來集合在一起測試
#include
#include #include
... TestSuite suite; TestResult result; suite.addTest(new
TestCaller ("testEquality",
&ComplexNumberTest::testEquality)); suite.addTest(new
TestCaller ("testAddition",
&ComplexNumberTest::testAddition)); suite.run (&result);
TestSuite 物件也可以再透過其它的 TestSuite 物件來集合起來一起測試,例如:
TestSuite suite; TestResult
result; suite.addTest (ComplexNumberTest::suite ()); suite.addTest
(SurrealNumberTest::suite ()); suite.run (&result);
... suite() 函式範例如下: public: static Test *suite () // Note:
TestSuite is derived from Test { TestSuite *suiteOfTests
= new TestSuite; suiteOfTests->addTest( new TestCaller
("testEquality", testEquality)); suiteOfTests->addTest(
new TestCaller ("testAddition",
testAddition)); return suiteOfTests; }
- 或是藉由另外一個 TextTestRunner 類別的物件來完成測試:
#include #include
... int main( int argc, char* argv[] ) { CppUnit::TextTestRunner
runner; runner.addTest(CppUnit::TestFactoryRegistry:: getRegistry().makeTest());
runner.run(); return 0; }
以上測試都會開啟一文字視窗來顯示結果。
如果要使用 Win32 GUI TestRunner 類別時主要有兩種方法:
- 各個 TestCase 及 TestSuite 定義同前所述:
#include ... TestRunner
runner; runner.addTest (ExampleTestCase::suite ()); runner.addTest
(ComplexNumberTest::suite ()); runner.run ();
- 利用 include/cppunit/extensions/HelperMacros.h 中定義的 CPPUNIT_TEST_SUITE()
CPPUNIT_TEST() CPPUNIT_TEST_SUITE_END() 等巨集來加入一個一個測試,例如:
#include ...
CPPUNIT_TEST_SUITE( XXXXTest ); CPPUNIT_TEST( testRoutine1
); CPPUNIT_TEST( testRoutine2 ); CPPUNIT_TEST_SUITE_END();
並用
CPPUNIT_TEST_SUITE_REGISTRATION( XXXXTest );
來登錄,然後使用 cppunit/extensions/TestFactoryRegistry.h 中的 TestFactoryRegistry
來產生 TestSuit, 範例如下:
#include #include
... TestRunner
runner; runner.addTest(CppUnit::TestFactoryRegistry:: getRegistry().makeTest());
runner.run();
參考文件:
- vc98\cppunit162\INSTALL-WIN32.txt
- vc98\cppunit162\examples\msvc6\HostApp\*.*
especially,
ExampleTestCase.h
ExampleTestCase.cpp
HostAppDoc.cpp CHostAppDoc::OnNewDocument()
- vc98\cppunit162\examples\msvc6\CppUnitTestApp\*.*
especially, CppUnitTestApp::RunTests()
- vc98\cppunit162\examples\cppunittest\*.*
especially, CppUnitTestMain.cpp main()
- vc98\cppunit162\docs\cookbook.html
- vc98\cppunit162\docs\index.html
- Martin Fowler's Refactoring Chapter 4
|
|