青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-341  評論-2670  文章-0  trackbacks-0
    現在市面上已經有很多Unit Test的工具了。對于C++來說最為著名的莫過于CppUnit。CppUnit已經具有豐富的功能,例如UI、報告生成等等。那么為什么還要自己做Unit Test工具呢?主要還是為了學習,其次是可以為自己的特殊需求打造特殊的工具。

    隨著程序越來越復雜,Unit Test的重要作用已經不言而喻了。在Kernel FP的開發過程中,由于經常需要重構,于是Unit Test就已經成為必不可少的工具之一了。接口不變化的重構,可以通過足夠的Unit Test來在最大的程度上保證新的代碼不會引發更多問題。為了開發Unit Test的工具,我們首先了解一下一個Unit Test的典型需求是什么。

    Unit Test作為一種檢驗代碼是否有已經預期錯誤的手段,我們需要很多的TestCase,每一個TestCase又需要若干的面向具體問題的檢查,稱為TestMethod,每一個TestMethod又需要若干的條件判斷。我們可以在Unit Test當中寫很多返回bool類型的表達式,并且讓true代表成功,false代表失敗。于是Unit Test的一個重要功能就是執行我們定義的所有條件表達式,并作出統計。

    Unit Test的輸入可以有很多,但是測試代碼是必不可少的。于是我們需要一些容器來包含代碼,并且讓一個處于后臺的執行引擎來依次執行我們的代碼然后輸出信息。

    Unit Test的輸出無非就是Unit Test的執行狀態,也就是每一個條件表達式所在的位置、結果以及附帶的供我們查看的文字信息。那么應該如何處理輸出信息呢?在自己開發Unit Test框架的過程中,我們可以將信息進行分類,然后使用Observer模式將信息傳播出去:
 1         class IVL_TestRecorder : public IVL_Interface
 2         {
 3         public:
 4             virtual void                    BeginRun(VL_TestRunner* Runner)=0;
 5             virtual void                    EndRun()=0;
 6             virtual void                    BeginCase(VInt Index)=0;
 7             virtual void                    EndCase()=0;
 8             virtual void                    BeginMethod(VInt Index)=0;
 9             virtual void                    EndMethod()=0;
10             virtual void                    IgnoreMethod(VInt Index)=0;
11             virtual void                    ExceptionOccur()=0;
12             virtual void                    Pass(VUnicodeString Message)=0;
13             virtual void                    Fail(VUnicodeString Message)=0;
14             virtual void                    Print(VUnicodeString Message)=0;
15         };

    從上面的接口我們可以看到,每一步的開始和結束,以及條件的信息以及結構都期望輸入到一個IVL_TestRecorder對象里面。這里我們可以做很多事情。首先VL_TestRunner可以,而且必須可以獲得用于分辨每一個TestMethod的信息,譬如說TestCase的名字以及TestMethod的名字。其次,無論TestMethod里面做了什么樣的事情,VL_TestRunner都應當盡可能地捕捉到。

    在IVL_TestRecorder的幫助之下我們就可以實現一些工具了。譬如一個用于將信息傳播給一堆Recorder的Recorder,譬如一個用于生成HTML報告的Recorder,譬如一個用于統計的Recorder,譬如一個將信息發布到GUI上的Recorder等等。第一種Recorder將Recorder變成了樹,然后其余的Recorder只需要裝飾葉節點,就可以獲得一個可擴展性非常強的Recorder工具了。

    當然,接下去的問題是如何包含測試代碼。我們可以將很多VL_TestCase的實例裝入VL_TestRunner,并且將很多函數裝入VL_TestCase。這個時候boost的functor就可以大大簡化這個過程,當然我自己并沒有使用它,而是自己寫了一個類似的工具。于是VL_TestRunner的職責就是調用VL_TestCase,VL_TestCase的職責就是調用TestMethod,而TestMethod則是我們寫的測試代碼,職責是測試一系列的條件并輸出信息。通過兩個類以及一些宏的配合,我們最終可以得到類似于下面的結果:
 1 class TestCase1 : public VL_TestCase
 2 {
 3 public:
 4     TestCase1()
 5     {
 6         VL_UNITTEST_ADDMETHOD(TestCase1,TestMethod1);
 7         VL_UNITTEST_ADDMETHOD(TestCase1,TestMethod2);
 8         VL_UNITTEST_ADDMETHOD(TestCase1,TestMethod3);
 9     }
10 
11     void TestMethod1()
12     {
13         VL_UNITTEST_CHECK(1==1);
14         VL_UNITTEST_CHECK(1==0);
15     }
16 
17     void TestMethod2()
18     {
19         VL_UNITTEST_ASSERT(1==1);
20         VL_UNITTEST_PRINT(L"MESSAGE");
21     }
22 
23     void TestMethod3()
24     {
25         VL_UNITTEST_ASSERT(1==0);
26         VL_UNITTEST_PRINT(L"MESSAGE");
27     }
28 };
29 
30 class TestCase2 : public VL_TestCase
31 {
32 public:
33     TestCase2()
34     {
35         VL_UNITTEST_ADDMETHOD(TestCase2,TestMethod1);
36         VL_UNITTEST_ADDMETHOD(TestCase2,TestMethod2);
37     }
38 
39     void TestMethod1()
40     {
41         int a=0;
42         a=a/a;
43         VL_UNITTEST_PRINT(L"REACH");
44     }
45 
46     void TestMethod2()
47     {
48         throw "XXX";
49         VL_UNITTEST_PRINT(L"REACH");
50     }
51 };
52 
53 class TestRunner : public VL_TestRunner
54 {
55 public:
56     TestRunner()
57     {
58         VL_UNITTEST_ADDCASE(TestCase1);
59         VL_UNITTEST_ADDCASE(TestCase2);
60     }
61 };


    上面的宏都是一些很簡單的技巧,就不詳細講了。如果熟悉宏的語法的話,則可以很容易的實現它們。至于數據結構上,VL_TestRunner可以看成一個VL_TestCase的數組,而VL_TestCase則包含了一個函數指針的數組。

    那這兩個框架類的接口應當是什么樣子的呢?我們允許Runner在內部添加TestCase,允許TestCase在內部添加TestMethod,并且允許從Runner獲得整個結構的內容,最后Runner應當能夠執行所有的TestMethod,于是接口很自然地就會變成這個樣子:

 1 class VL_TestCase : public VL_Base
 2 {
 3     friend class VL_TestRunner;
 4 private:
 5     VL_TestMethodMap                FMethods;
 6     IVL_TestRecorder*                FCurrentRecorder;
 7 
 8     VBool                            RunCPPEHProtected(IVL_TestRecorder* Recorder , VL_TestMethod* Method);
 9     VBool                            RunSEHProtected(IVL_TestRecorder* Recorder , VL_TestMethod* Method);
10     void                            Run(IVL_TestRecorder* Recorder , VL_TestRunner* Runner , VInt CaseIndex , IVL_TestFilter* Filter);
11 
12 protected:
13     virtual void                    Initialize();
14     virtual void                    Finalize();
15 
16     void                            AddMethod(VUnicodeString Name , VL_TestMethodPtr Method);
17     IVL_TestRecorder*                GetCurrentRecorder();
18 
19 public:
20     VL_TestCase();
21 
22     VInt                            GetMethodCount();
23     VUnicodeString                    GetMethodName(VInt Index);
24 };
25 typedef VL_AutoPtr<VL_TestCase>                                    VL_TestCasePtr;
26 typedef VL_List<VL_TestCasePtr , false , VL_TestCase*>            VL_TestCaseList;
27 typedef VL_ListedMap<VUnicodeString , VL_TestCasePtr>            VL_TestCaseMap;
28 
29 class VL_TestRunner : public VL_Base
30 {
31 protected:
32     VL_TestCaseMap                    FCases;
33     void                            AddCase(VUnicodeString Name , VL_TestCase* Case);
34 
35 public:
36     VL_TestRunner();
37 
38     VInt                            GetCaseCount();
39     VUnicodeString                    GetCaseName(VInt Index);
40     VL_TestCase*                    GetCase(VInt Index);
41     VL_TestCase*                    GetCase(VUnicodeString Name);
42     void                            Run(IVL_TestRecorder* Recorder , IVL_TestFilter* Filter);
43 };

    通過private的run加上一個friend class VL_TestRunner的聲明,還有處于protected內的若干函數,我們將每一個函數的可視范圍都清晰地定義了下來。好了,有了Recorder和Runner,我們就可以從外部監視Unit Test的執行狀態,并且不需要修改任何代碼就能進行擴展。因此我們可以很簡單的寫一個Console Host來執行Unit Test,也可以寫一個GUI Host來執行Unit Test。今天由于時間的關系,我只實現了一個簡單的Console Host,并且讓這個Console Host自己將Recorder交給Runner進行監視。這可以使得main函數非常簡單地完成:
1 void vlmain()
2 {
3     GetConsole()->SetPauseOnExit(true);
4     GetConsole()->SetTestMemoryLeaks(true);
5     GetConsole()->SetTitle(L"Vczh Library++ 2.0 Unit Test Framework");
6 
7     TestRunner Runner;
8     SimpleConsoleTestHost(&Runner);
9 }

    其中,SimpleConsoleTestHost的內容如下:
 1 void SimpleConsoleTestHost(VL_TestRunner* Runner , IVL_TestRecorder* Recorder)
 2 {
 3     VL_TestRecorderList RecorderList;
 4     VL_TestConsoleRecorder ConsoleRecorder;
 5     VL_TestAllAcceptFilter AllAcceptFilter;
 6 
 7     if(Recorder)
 8     {
 9         RecorderList.Add(Recorder);
10     }
11     RecorderList.Add(&ConsoleRecorder);
12     Runner->Run(&RecorderList,&AllAcceptFilter);
13 }

    讓我們看看結果吧!

    這里貼出VL_UNITTEST_*的內容:
 1 #define VL_UNITTEST_ADDCASE(CLASSNAME)                                \
 2     do{                                                                \
 3         AddCase(L#CLASSNAME,(new CLASSNAME()));}                    \
 4     while(0)
 5 
 6 #define VL_UNITTEST_ADDMETHOD(CLASSNAME,METHODNAME)                    \
 7     do{                                                                \
 8         VL_TestMethod* Method=new VL_TestMethod;                    \
 9         Method->Bind(this,&CLASSNAME::METHODNAME);                    \
10         this->AddMethod(L#METHODNAME,Method);                        \
11     }while(0)
12 
13 #define VL_UNITTEST_PRINT(MESSAGE)                                    \
14     do{                                                                \
15         GetCurrentRecorder()->Print(MESSAGE);                        \
16     }while(0)
17 
18 #define VL_UNITTEST_TEST(CONDITION,MESSAGE,ISASSERT)                \
19     do{                                                                \
20         if(CONDITION)                                                \
21         {                                                            \
22             GetCurrentRecorder()->Pass(MESSAGE);                    \
23         }                                                            \
24         else                                                        \
25         {                                                            \
26             GetCurrentRecorder()->Fail(MESSAGE);                    \
27             if(ISASSERT)                                            \
28             {                                                        \
29                 return;                                                \
30             }                                                        \
31         }                                                            \
32     }while(0)
33 
34 #define VL_UNITTEST_CHECK_MESSAGE(CONDITION,MESSAGE)                \
35     VL_UNITTEST_TEST(CONDITION,MESSAGE,false)
36 
37 #define VL_UNITTEST_CHECK(CONDITION)                                \
38     VL_UNITTEST_CHECK_MESSAGE(CONDITION,L#CONDITION)
39 
40 #define VL_UNITTEST_CHECK_FAIL(MESSAGE)                                \
41     VL_UNITTEST_CHECK_MESSAGE(false,MESSAGE)
42 
43 #define VL_UNITTEST_ASSERT_MESSAGE(CONDITION,MESSAGE)                \
44     VL_UNITTEST_TEST(CONDITION,MESSAGE,true)
45 
46 #define VL_UNITTEST_ASSERT(CONDITION)                                \
47     VL_UNITTEST_ASSERT_MESSAGE(CONDITION,L#CONDITION)
48 
49 #define VL_UNITTEST_ASSERT_FAIL(MESSAGE)                            \
50     VL_UNITTEST_ASSERT_MESSAGE(false,MESSAGE)

    接下來就是寫一些Test、完成GUI Host、完成Kernel FP了。
posted on 2008-11-13 09:38 陳梓瀚(vczh) 閱讀(2553) 評論(4)  編輯 收藏 引用 所屬分類: 其他

評論:
# re: 打造自己的Unit Test工具 2008-11-13 16:50 | LOGOS
輪子,雖然是以學習為目的

使用太繁瑣,我現在手頭上使用的非常方便
TEST( testa )
{
}

TEST_F( fixture , testb )
{
}  回復  更多評論
  
# re: 打造自己的Unit Test工具 2008-11-13 18:45 | 陳梓瀚(vczh)
你那個需要全局變量。而且host是自動的話,那么等于失去了添加功能的機會。除了修改測試的代碼。  回復  更多評論
  
# re: 打造自己的Unit Test工具 2008-11-14 04:19 | 空明流轉
相比之下我還是個MACRO控,以前我也寫過UnitTest的東東。。。  回復  更多評論
  
# re: 打造自己的Unit Test工具 2008-11-17 04:33 | Lnn
不錯哎  回復  更多評論
  
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产aⅴ天堂久久| 一个色综合av| 日韩视频免费在线| 国内成人精品一区| 国产一区二区三区网站| 国产日韩亚洲欧美| 国内精品国语自产拍在线观看| 国产精品成人在线观看| 国产精品福利片| 国产精品亚洲激情| 国产视频亚洲| 在线日韩中文字幕| 亚洲欧洲日本专区| 亚洲视频观看| 欧美一区二区三区四区视频| 久久大逼视频| 另类酷文…触手系列精品集v1小说| 快播亚洲色图| 99riav久久精品riav| 欧美一区二区三区免费观看视频 | 国产女人18毛片水18精品| 国产精品视频男人的天堂| 国际精品欧美精品| 99一区二区| 久久精品国产清高在天天线| 巨乳诱惑日韩免费av| 亚洲日本中文字幕区| 亚洲日本欧美天堂| 久久精品国产综合精品| 欧美日韩成人在线视频| 国产午夜精品福利| 亚洲免费观看视频| 久久久久久一区二区三区| 免费成人你懂的| 一区二区三区 在线观看视| 久久在线视频| 国产麻豆日韩| 亚洲香蕉网站| 亚洲高清久久网| 亚洲欧美日韩国产一区| 欧美精品久久久久久久久久| 国产一区在线观看视频| 中文一区二区| 亚洲高清免费| 久久久精品久久久久| 国产精品美腿一区在线看| 亚洲国产精品一区| 久久人人爽人人爽爽久久| 99精品国产热久久91蜜凸| 久久久久久久久蜜桃| 国产区在线观看成人精品| 亚洲网站视频| 亚洲欧洲精品一区二区三区波多野1战4| 久久不射电影网| 国产夜色精品一区二区av| 亚洲免费一级电影| 艳女tv在线观看国产一区| 欧美激情第4页| 亚洲精品一二| 亚洲黄色影片| 欧美国产精品va在线观看| 伊人久久大香线蕉综合热线| 久久精品视频播放| 欧美中文字幕视频在线观看| 国产精品欧美久久久久无广告| 亚洲一区在线免费观看| 亚洲视频播放| 国产女人精品视频| 久久久精品一品道一区| 久久国产精品久久w女人spa| 精品96久久久久久中文字幕无| 久久久久久综合| 久久久久久久999| 亚洲第一页中文字幕| 欧美顶级大胆免费视频| 欧美激情一区二区三区在线| 日韩亚洲在线观看| 一道本一区二区| 国产欧美一区二区精品秋霞影院| 国产精品制服诱惑| 亚洲欧美日韩在线不卡| 午夜欧美大尺度福利影院在线看| 国产日本欧美在线观看| 老司机精品福利视频| 奶水喷射视频一区| 中文亚洲视频在线| 欧美在线免费播放| 亚洲精品午夜精品| 亚洲一区影院| 在线观看一区| 亚洲美女毛片| 国产一区二三区| 亚洲国产精品va在线看黑人| 欧美日韩www| 久久久成人网| 欧美日韩三级视频| 久久精品91久久久久久再现| 久久噜噜噜精品国产亚洲综合 | 激情五月综合色婷婷一区二区| 欧美国产日韩一区二区| 欧美视频官网| 欧美大片在线观看| 国产精品成人一区二区艾草| 欧美18av| 国产欧美精品在线观看| 亚洲国产91| 国内揄拍国内精品久久| 亚洲精品一区久久久久久| 国模精品一区二区三区| 一本色道久久| 亚洲高清资源| 亚洲综合视频一区| 一区二区av| 狼人天天伊人久久| 久久精品日产第一区二区三区| 欧美日韩在线观看一区二区| 欧美第一黄色网| 国产在线视频欧美一区二区三区| 日韩亚洲欧美中文三级| 亚洲人成亚洲人成在线观看图片 | 亚洲高清在线观看一区| 国内精品久久久| 亚洲影视中文字幕| 亚洲午夜久久久久久久久电影网| 可以免费看不卡的av网站| 久久久噜噜噜久久久| 国产精品稀缺呦系列在线| 99精品免费| 亚洲视频图片小说| 欧美久久婷婷综合色| 亚洲国产日本| 亚洲激情综合| 欧美成人r级一区二区三区| 免费欧美在线| 亚洲国产欧美一区| 麻豆精品在线观看| 亚洲第一在线视频| 亚洲精品美女在线| 欧美大片在线观看| 亚洲黄色片网站| 999亚洲国产精| 欧美精品九九99久久| 亚洲免费人成在线视频观看| 欧美久久一级| 99国产一区二区三精品乱码| 亚洲天堂av在线免费| 欧美激情亚洲精品| 一区二区精品| 欧美在线一二三| 一区二区三区在线高清| 久久久www成人免费毛片麻豆| 久久亚洲高清| 亚洲黄色免费电影| 欧美日韩不卡合集视频| 日韩一级在线观看| 午夜在线视频观看日韩17c| 国产精品影音先锋| 久久精品中文| 亚洲国产精品一区二区www| 亚洲最新视频在线| 国产精品日韩精品| 久久精品系列| 亚洲日韩中文字幕在线播放| 在线亚洲免费视频| 国产视频亚洲精品| 欧美不卡视频| 亚洲欧美亚洲| 欧美激情一区二区三区不卡| 这里只有精品丝袜| 国产亚洲成人一区| 欧美精品自拍| 欧美在线亚洲在线| 亚洲精品一线二线三线无人区| 亚洲欧美激情视频| 亚洲第一精品夜夜躁人人躁| 欧美日韩亚洲高清一区二区| 欧美一区二区黄| 亚洲国产裸拍裸体视频在线观看乱了 | 国产日韩一区二区三区在线播放| 久久九九国产| 亚洲最快最全在线视频| 美女久久一区| 午夜精品影院| 99热免费精品| 在线观看一区视频| 国产美女精品视频| 欧美日本免费一区二区三区| 欧美伊人精品成人久久综合97| 亚洲国产精品嫩草影院| 欧美一区在线直播| 在线视频精品一区| 亚洲国产专区校园欧美| 国产精品自拍在线| 欧美日韩一区视频| 欧美凹凸一区二区三区视频| 欧美在线播放一区| 亚洲在线观看免费视频| 亚洲麻豆av| 最新国产拍偷乱拍精品| 免费成人性网站|