• <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>

            C++ Programmer's Cookbook

            {C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

            vs2005 的單元測試

            使用 Visual Studio 對公共方法進行單元測試,跟以前 NUnit 一樣,都是引用需要的類,然后對公共方法進行測試。

              但是 Visual Studio 還可以對類的私有方法進行測試。而Visual Studio 不允許測試代碼跟實際代碼放在一個項目中,我們來看看是Visual Studio UnitTest如何做的。

              比如我們有這樣一個私有方法

            ?

            namespace?ClassLibrary1{
             
            public?class?DivisionClass{
              
            private?int?Divide_private(int?numerator,?int?denominator){
               
            return?numerator?/?denominator;
              }

             }

            }

            ?

              我們只要在這個私有方法的右鍵菜單中選擇 創建單元測試,系統就自動產生了這個私有方法的單元測試代碼。

              下面我們來分析產生的單元測試代碼,看Visual Studio UnitTest 是如何對私有方法進行單元測試的

              簡單來說,Visual Studio UnitTest 生成私有方法的單元測試時,將自動創建一個私有訪問器。私有訪問器是測試方法用于訪問私有代碼的方法。單元測試生成對私有訪問器的調用,然后通過私有訪問器來調用私有方法。私有訪問器駐留在測試項目中的文件中;因此將被編譯為測試項目程序集。

              具體來看測試項目:

              首先我們可以看到一個名為 VSCodeGenAccessors.cs 的新文件被創建,

              這個文件包含兩個類:

              internal 類型的 BaseAccessor 類 和 派生自它的 ClassLibrary1_DivisionClassAccessor 類

              BaseAccessor 類是通用的訪問器基類。

              ClassLibrary1_DivisionClassAccessor 類 則是對你要訪問類的私有方法進行了反射封裝,這樣你就可以通過操作這個類來操作該私有方法了。如下面代碼:

            using?Microsoft.VisualStudio.TestTools.UnitTesting;

            namespace?TestProject1{
             [System.Diagnostics.DebuggerStepThrough()]
             [System.CodeDom.Compiler.GeneratedCodeAttribute(
            "Microsoft.VisualStudio.TestTools.UnitTestGeneration",?"1.0.0.0")]
             
            internal?class?BaseAccessor?{

              
            protected?Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject?m_privateObject;

              
            protected?BaseAccessor(object?target,?Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType?type)?{
               m_privateObject?
            =?new?Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(target,?type);
              }


              
            protected?BaseAccessor(Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType?type)?:
              
            this(null,?type)?{}

              
            internal?virtual?object?Target?{
               
            get?{
                
            return?m_privateObject.Target;
               }

              }


              
            public?override?string?ToString()?{
               
            return?this.Target.ToString();
              }


              
            public?override?bool?Equals(object?obj)?{
               
            if?(typeof(BaseAccessor).IsInstanceOfType(obj))?{
                obj?
            =?((BaseAccessor)(obj)).Target;
               }

               
            return?this.Target.Equals(obj);
              }


              
            public?override?int?GetHashCode()?{
               
            return?this.Target.GetHashCode();
              }

             }


             [System.Diagnostics.DebuggerStepThrough()]
             [System.CodeDom.Compiler.GeneratedCodeAttribute(
            "Microsoft.VisualStudio.TestTools.UnitTestGeneration",?"1.0.0.0")]
             
            internal?class?ClassLibrary1_DivisionClassAccessor?:?BaseAccessor?{

             
            protected?static?Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType?m_privateType?=?new?Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType(typeof(global::ClassLibrary1.DivisionClass));

             
            internal?ClassLibrary1_DivisionClassAccessor(global::ClassLibrary1.DivisionClass?target)?:
             
            base(target,?m_privateType)?{}

             
            internal?int?Divide_private(int?numerator,?int?denominator)?{
              
            object[]?args?=?new?object[]?{
               numerator,
               denominator}
            ;
              
            int?ret?=?((int)(m_privateObject.Invoke("Divide_private",?new?System.Type[]?{
               
            typeof(int),
               
            typeof(int)}
            ,?args)));
               
            return?ret;
              }
             
             }

            }


              注意:當您更改正在測試的代碼文件中的私有方法時,這個訪問器可能無法正常工作,需要重新生成專用訪問器(ClassLibrary1_DivisionClassAccessor 類)。

              整理一下就是:

              這個訪問器,是通過反射的方式實現的。

              VSUT利用自動代碼生成技術,在單元測試項目中先來給你要測試的類生成一個名字叫XXXAccessor的訪問器。

              這個訪問器會把需要測試類的需要測試的私有方法暴露出來,這種方式,無論是私有還是公共的屬性和方法。這種方式可以很方便的給測試方法搭建測試環境,MOCK對象的注入也容易了。在測試調用的時候,就簡單的只有下面的代碼了:

            [DeploymentItem("ClassLibrary1.dll")]
            [TestMethod()]
            public?void?Divide_privateTest()
            {
             DivisionClass?target?
            =?new?DivisionClass();
             TestProject1.ClassLibrary1_DivisionClassAccessor?accessor?
            =?new? TestProject1.ClassLibrary1_DivisionClassAccessor(target);
             
            int?numerator?=?4;
             
            int?denominator?=?0;
             
            int?expected?=?0;
             
            int?actual;
             actual?
            =?accessor.Divide_private(numerator,?denominator);
             Assert.AreEqual(expected,?actual,?
            "ClassLibrary1.DivisionClass.Divide_private?未返回所需的值。");
             Assert.Inconclusive(
            "驗證此測試方法的正確性。");
            }



            Visual Studio 2005 新增的測試功能使我們的開發工作更為快捷,代碼質量在一定程度上有所提高。想必大家對類的單元測試已經比較熟悉,這里我們來看看它提供的另一項更為有趣的測試——用戶界面自動化測試。事實上這個測試的本質仍是單元測試,單元測試的各種方法在用戶界面測試中仍然可用。

              我們以一個簡單的 Windows Form 應用程序為例(在 Visual Studio 2005 Team System 下演示,其它版本亦可參考)。如圖所示,這是一個一元二次方程的求解程序。

              在 Visual Studio 2005 中加載這個程序的工程,切換到待測試窗體(Form1)的源代碼視圖。添加一個用戶界面測試最簡單的方法是在事件函數聲明代碼上右擊鼠標,在快捷菜單中點擊“Create Unit Tests”。在彈出的對話框中點選待測試的函數(特別是事件函數),確定。當然,手工添加一個單元測試項目也是可以的,但通過快捷菜單自動生成的代碼中包含了一些測試輔助類和對象的聲明,使用起來更加方便。

              本例中,我們由 btnWorkOut_Click 創建單元測試,自動生成的代碼如下:

            [DeploymentItem("XandY.exe")]
            [TestMethod()]

            public void btnWorkOut_ClickTest()
            {
             Form1 target = new Form1();
             MyTestProject.XandY_Form1Accessor accessor = new MyTestProject.XandY_Form1Accessor(target);
             object sender = null; // TODO: Initialize to an appropriate value
             EventArgs e = null; // TODO: Initialize to an appropriate value
             accessor.btnWorkOut_Click(sender, e);
             Assert.Inconclusive("A method that does not return a value cannot be verified.");
            }

              熟悉單元測試的朋友應該明白 [TestMethod()] 屬性的含義。在這個測試函數中,target 是待測試窗體的一個實例。sender 和 e 是各個事件函數必備的參數,一般情況下取 null 即可。最重要的是 accessor 對象,它是我們進行用戶界面自動化測試的“總代理”。通過它可以訪問到待測試窗體的各個方法、屬性和控件,并可調用控件已聲明的各個事件。由此,我們可以用 accessor 模擬使用者通過鍵盤、鼠標對用戶界面的各項操作,同時即時獲知程序中各個變量的狀態。有興趣的朋友可以讀讀 XandY_Form1Accessor 類的定義,了解這個“總代理”工作的奧秘。

              我們對測試代碼進行以下修改,以便對程序運行的正確性進行測試。

            [DeploymentItem("XandY.exe")]
            [TestMethod()]

            public void btnWorkOut_ClickTest()
            {
             Form1 target = new Form1();
             MyTestProject.XandY_Form1Accessor accessor = new MyTestProject.XandY_Form1Accessor(target);
             object sender = null; // TODO: Initialize to an appropriate value
             EventArgs e = null; // TODO: Initialize to an appropriate value
             target.Show();
             target.Refresh();
             System.Threading.Thread.Sleep(1000);
             accessor.textBox1.Text = "2";
             accessor.textBox2.Text = "4";
             accessor.textBox3.Text = "2";
             target.Refresh();
             System.Threading.Thread.Sleep(1000);
             accessor.btnWorkOut_Click(sender, e);
             target.Refresh();
             Assert.IsTrue(accessor.d >= 0);
             Assert.IsNotNull(accessor.xx);
             Assert.IsNotNull(accessor.xy);
             Console.WriteLine("X1 = " + accessor.textBox4.Text);
             Console.WriteLine("X2 = " + accessor.textBox5.Text);
             System.Threading.Thread.Sleep(1000);
             target.Close();
            }

              以上代碼中,我們通過 target.Show() 呈現窗體,通過 target.Refresh() 可以即時地刷新窗體內容在屏幕的顯示,通過 System.Threading.Thread.Sleep(1000) 來延時。這幾段代碼都不是必需的,加入它們是為了便于程序反應和測試者觀察,我們也完全可以在不顯示用戶界面的情況下更快地運行自動測試。至于用 Assert 來監控變量狀態和用 Console 做輸出,用過單元測試的朋友都應該了解。

              此時,我們運行這個測試,就會在屏幕上先后看到窗體被加載,三個文本框被填入數據,計算結果出現在下面的文本框中,最后窗體被關閉。

              再來看看測試結果的輸出,符合我們的預期。

              Visual Studio 2005 的用戶界面自動化測試就是這么簡單。對于一般的測試,它使測試人員不必深究應用程序底層的實現。當然,對于本例這樣簡單的程序,我們用不著這么麻煩的測試,但是對于用戶界面更加復雜的程序,操作上存在更多的組合方式,手工測試的繁瑣程度以及查找問題的難度便大大上升了。使用 Visual Studio 2005 提供的自動化測試手段將在很大程度上減輕測試人員的負擔。有興趣的朋友甚至可以在這個基礎上進行二次開發,引入自動化測試腳本等專業測試方案,實現通用性更強的用戶界面自動化測試

            posted on 2006-04-20 19:34 夢在天涯 閱讀(2855) 評論(3)  編輯 收藏 引用 所屬分類: C#/.NET

            評論

            # re: vs2005 的單元測試 2011-07-31 13:32 HANSONCorinne25

            Different people in every country take the <a href="http://bestfinance-blog.com/topics/personal-loans">personal loans</a> from various creditors, just because this is easy.   回復  更多評論   

            # re: vs2005 的單元測試 2011-08-07 06:33 already written essay

            Different students in the world cognize that the essays writing service will supply us with the essay buy. Thus, it would be simple to order an essay.   回復  更多評論   

            # re: vs2005 的單元測試 2012-09-20 11:37 CV templates

            Have no clue how to generate remarkable CV yourself? Writing companies that function on the net will help you out with pleasure when you require to deal with professional resume writers perfect-resume.com.  回復  更多評論   

            公告

            EMail:itech001#126.com

            導航

            統計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1804603
            • 排名 - 5

            最新評論

            閱讀排行榜

            国产日韩久久久精品影院首页| 午夜精品久久久久久久无码| 久久亚洲AV成人无码软件| 久久男人AV资源网站| 久久伊人精品一区二区三区| 久久久久久无码Av成人影院 | 国产99久久久国产精品~~牛| 人人狠狠综合久久亚洲88| 久久久久国产精品三级网| 亚洲欧美日韩久久精品| 久久国产精品无码HDAV| 精品国产婷婷久久久| 亚洲国产另类久久久精品黑人 | 国产精品一区二区久久精品涩爱| 亚洲国产精品无码久久SM| 久久精品国产亚洲综合色| 婷婷久久综合九色综合九七| 人妻无码αv中文字幕久久| 看全色黄大色大片免费久久久| 亚洲va久久久噜噜噜久久狠狠| 久久国产综合精品五月天| 亚洲AV无码久久精品色欲| 老司机午夜网站国内精品久久久久久久久 | 新狼窝色AV性久久久久久| 99久久国产综合精品成人影院| 亚洲综合精品香蕉久久网| 久久久久久亚洲精品无码| 色综合久久久久网| 人妻无码αv中文字幕久久琪琪布 人妻无码久久一区二区三区免费 人妻无码中文久久久久专区 | 亚洲狠狠久久综合一区77777| 伊人久久大香线焦AV综合影院| 久久久久久久亚洲精品| 国产亚洲成人久久| 一本大道加勒比久久综合| 99久久无色码中文字幕| 久久久久久久亚洲Av无码| 午夜欧美精品久久久久久久 | www.久久99| 久久777国产线看观看精品| 久久精品九九亚洲精品| 久久精品国产亚洲av高清漫画|