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

隨筆-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>
            亚洲大片av| 国产一区激情| 久久久久久久网| 欧美人妖另类| 欧美一区二区精品在线| 亚洲男人的天堂在线aⅴ视频| 亚洲视频综合| 欧美在线不卡| 欧美大片在线观看一区二区| 欧美激情视频在线播放| 国产精品v亚洲精品v日韩精品 | 亚洲一区www| 午夜久久tv| 欧美国产欧美综合| 正在播放亚洲一区| 久久九九精品| 欧美日韩亚洲高清一区二区| 国产伦精品一区二区三区高清| 黑人巨大精品欧美一区二区 | 亚洲第一福利在线观看| 一区二区国产精品| 久久午夜国产精品| 日韩视频免费观看高清完整版| 欧美制服第一页| 欧美日韩中文字幕| 精品96久久久久久中文字幕无| 一区二区三区日韩在线观看| 久久一区精品| 亚洲视频二区| 欧美大片在线观看| 国产又爽又黄的激情精品视频| 亚洲国内欧美| 久久精品中文| 9i看片成人免费高清| 久久精品水蜜桃av综合天堂| 欧美日韩一区不卡| 亚洲精品裸体| 蜜臀av性久久久久蜜臀aⅴ| 一区二区毛片| 欧美国产高潮xxxx1819| 一区在线观看| 久久婷婷国产综合精品青草| 一区二区三区免费看| 欧美成人在线免费视频| 影音先锋国产精品| 久久亚洲春色中文字幕| 亚洲欧美怡红院| 欧美日韩中文字幕在线| 日韩亚洲一区在线播放| 欧美第十八页| 欧美成人精品在线| 亚洲国产综合91精品麻豆| 久热国产精品视频| 久久久精品日韩| 极品av少妇一区二区| 午夜日韩视频| 亚洲午夜影视影院在线观看| 国产片一区二区| 欧美a级大片| 欧美在线亚洲综合一区| 欧美va亚洲va日韩∨a综合色| 欧美日韩精品一区二区| 亚洲大片一区二区三区| 久久午夜精品一区二区| 久久精品亚洲精品国产欧美kt∨| 国产精品yjizz| 亚洲小说欧美另类婷婷| 亚洲精品在线免费| 欧美日韩在线视频首页| 亚洲天堂av电影| 在线亚洲欧美| 国产日韩欧美不卡| 久久综合99re88久久爱| 久久久蜜桃一区二区人| 在线精品视频在线观看高清| 免费成人av| 欧美激情一二区| 亚洲一区二区动漫| 亚洲一区二区三区四区五区黄| 国产精品美女久久| 久久久91精品| 欧美va天堂va视频va在线| 99成人精品| 亚洲欧美日韩综合| 亚洲国产精品成人综合色在线婷婷| 美日韩精品免费| 欧美日本一区二区三区| 午夜日韩福利| 久久蜜桃香蕉精品一区二区三区| 亚洲欧洲精品天堂一级| 亚洲视频大全| 亚洲激情在线播放| 亚洲视频图片小说| 在线精品视频免费观看| 日韩视频一区| 在线观看欧美精品| 一区二区三区欧美| 亚洲第一二三四五区| 一区二区久久久久| 在线不卡欧美| 亚洲一区二区三区免费观看 | 一本色道久久88亚洲综合88| 日韩亚洲欧美成人| 狠狠色狠狠色综合日日五| 亚洲人成7777| 国产精品日韩精品欧美精品| 美女久久一区| 国产日韩欧美综合| 日韩视频中文字幕| 亚洲国产精品一区二区www在线| 亚洲综合国产激情另类一区| 久久亚洲一区二区| 欧美日韩一区二区三区在线看| 久久九九免费| 国产精品v片在线观看不卡| 欧美成人综合| 精品51国产黑色丝袜高跟鞋| 亚洲一级网站| 亚洲特色特黄| 欧美日韩一区二区三区在线看| 欧美国产综合视频| 激情综合自拍| 久久精视频免费在线久久完整在线看| 亚洲一区二区三区四区中文| 欧美国产日韩在线| 亚洲福利国产精品| 伊人久久婷婷色综合98网| 亚洲一区二区在线| 亚洲欧美国产一区二区三区| 欧美日本一区| 亚洲六月丁香色婷婷综合久久| 亚洲国产欧美久久| 免费在线一区二区| 亚洲成在人线av| 亚洲精品免费在线| 欧美韩日一区| 亚洲精品在线视频| 亚洲一区二区成人| 国产精品你懂的在线欣赏| 亚洲淫片在线视频| 欧美一区二视频| 国产区精品在线观看| 亚洲欧美日韩另类精品一区二区三区 | 久久成人在线| 国内外成人在线| 欧美在线免费视频| 麻豆成人91精品二区三区| 尤妮丝一区二区裸体视频| 久久久精品视频成人| 免费在线欧美视频| 日韩图片一区| 国产精品高潮呻吟视频| 亚洲免费一级电影| 免费成人av在线| 一区二区欧美亚洲| 国产精品揄拍500视频| 久久狠狠久久综合桃花| 亚洲大片免费看| 亚洲线精品一区二区三区八戒| 国产精品日韩| 葵司免费一区二区三区四区五区| 亚洲电影免费在线观看| 亚洲一区在线直播| 国产一区亚洲| 欧美日本成人| 午夜精品久久久久久99热软件| 蜜桃av一区二区在线观看| 亚洲美女视频网| 国产精品你懂的在线| 久久久久久穴| 亚洲美女在线观看| 久久女同互慰一区二区三区| 一本色道精品久久一区二区三区| 国产视频精品免费播放| 欧美精品一区二区视频 | 99国产精品私拍| 欧美日韩精品一区二区三区四区| 亚洲淫性视频| 亚洲电影在线看| 亚洲专区一区二区三区| 国模大胆一区二区三区| 欧美日韩不卡一区| 欧美一区二区高清| 日韩一二三区视频| 欧美成人午夜影院| 亚洲欧美日韩另类| 亚洲精品美女久久久久| 国产一区二区三区免费在线观看| 免费观看国产成人| 欧美在线www| 在线一区二区日韩| 91久久精品美女高潮| 久久成人精品电影| 亚洲欧美日韩精品| 在线视频免费在线观看一区二区| 亚洲国语精品自产拍在线观看| 国产日韩亚洲| 国产欧美韩国高清| 国产精品日韩一区二区三区| 欧美日韩国产在线播放|