1. 程式人生 > >使用xUnit為.net core程式進行單元測試(1)

使用xUnit為.net core程式進行單元測試(1)

導讀

為什麼要編寫自動化測試程式(Automated Tests)?

  • 可以頻繁的進行測試
  • 可以在任何時間進行測試,也可以按計劃定時進行,例如:可以在半夜進行自動測試。
  • 肯定比人工測試要快。
  • 可以更快速的發現錯誤。
  • 基本上是非常可靠的。
  • 測試程式碼與生產程式碼緊密結合。
  • 使得開發團隊更具有幸福感!

自動化測試的分類:

縱軸表示測試的深度,也就是說測試的細緻程度。

橫軸則表示測試的覆蓋程度。

  • Unit Test 單元測試, 它可以測試一個類,或者一個類的某個功能,它具有很好的深度,但是對整個應用來說它不具備很好的覆蓋面。
  • Integration Test 整合測試,它沒有單元測試那麼細緻,但是具有相對較好的測試覆蓋面。例如它可以測試功能的組合,以及像資料庫或檔案系統這樣的外部資源等。
  • Subcutaneous Test 皮下測試,這種測試作用於UI層的下面一層,這也意味著它對整個應用來說有很好的覆蓋率,但是深度欠佳。那一個MVC結構的應用來說,它就是針對剛好在Controller下面一層的測試,對於Web service來說,它就是對節點下面那層的測試。
  • UI測試,它的測試覆蓋面很廣,直接從UI層面進行測試,但是深度欠佳。

從速度來看 單元是最快的,而UI測試是最慢的。

從脆弱性來看 UI測試是最差的,程式修改後極有可能需要修改測試程式碼,而單元測試是最好的。

是測試行為還是測試私有方法(private method)?

        public void
IncreaseHeartBeatRate() { HeartBeatRate = CalculateHeartBeatRate() + 2; } private int CalculateHeartBeatRate() { var random = new Random(); return random.Next(1, 100); }

大多數情況下單元測試都應該是針對類的行為進行測試的,也就是public方法。當然也純在不同的觀點。

如果想要對private方法進行測試的話,是有很多缺點的:

  • 首先需要修改方法的訪問限制需要從private改為public,這就破壞了面向物件的封裝性。
  • 再者,這其實測試的是類的具體實現細節,而不是類的行為。如果我們想要對類的內部進行重構的話,就會破壞測試,導致測試也必須重構。如果必須對private方法進行測試,那麼首先建議您把private修飾符改成internal,然後修改該專案(project)的AssemblyInfo.cs,它在專案的Debug或者Release資料夾下。程式碼如下:
[assembly: InternalsVisibleTo("Hospital.Tests")]

這表示Hospital.Tests這個測試專案可以訪問該專案生產程式碼(production code)的internal方法。

測試的三個階段 AAA

  • Arrange,這裡做一些先決的設定。例如建立物件例項,資料,輸入等等。
  • Act,在這裡執行生產程式碼並返回結果。例如呼叫方法,或者設定屬性(Properties)。
  • Assert,在這裡檢查結果。測試通過或者失敗。

xUnit.net

xUnit是一個測試框架,可以針對.net/core進行測試。

測試專案需引用被專案從而對其進行測試,測試專案同時需要引用xUnit庫。測試編寫好後,用Test Runner來執行測試。Test Runner可以讀取測試程式碼,並且會知道我們所使用的測試框架,然後執行,並顯示結果。目前可用的Test Runner包括vs自帶的Test Explorer,或者dotnet core命令列,以及第三方工具,例如resharper等等。

xUnit支援的平臺:

.net full, .net core, .net standard, uwp, xamarin.

xUnit的例子:

        [Fact]
        public void TestIncreaseHeartBeatRate()
        {
            var patient = new Patient(); // Arrange
            patient.IncreaseHeartBeatRate(); // Act
            Assert.InRange(patient.HeartBeatRate, 40, 100); // Assert
        }

安裝配置xUnit.net

a.使用Visual Studio 2017

首先建立一個C# library專案,叫Hospital(下面部分截圖有個拼寫錯誤,應該是Hospital),然後建立一個xUnit Test專案,叫Hospital.Tests:

 

可以看到Hospital.Tests已經包含裡這幾個庫:

然後為Hospital.Tests新增到Hospital專案的引用。

b.使用.net core 命令列

首先把剛才建立的Hospital.Tests專案移除(目錄需要手動刪除).

然後開啟專案位置:

按住shift開啟命令列:

用命令列建立專案:

建立 Hospital.Tests目錄,進入目錄,使用命令dotnet new xunit建立xUnit單元測試專案。

新增專案的引用:

最後新增專案到解決方案:

回到VS介面,提示重新載入:

確認後,VS中解決方案結構如:

做第一個測試

對測試專案的檔名進行一些重構,編寫以下程式碼,並進行Build:

從Test Explorer我們可以看到一個待測試的專案。

在這裡,我們可以對測試專案進行分組和排序,如圖:

想要執行所有的測試,就點選上面的Run All按鈕。如果像執行單個測試,那麼右擊選擇Run Selected Tests:

執行後,可以看到結果,Passed:

我們同樣可以通過命令列來進行測試:

進入到Tests目錄,執行 dotnet test命令,所有的測試都會被發現,然後被執行:

因為我們並沒有在測試方法中寫任何的Assert,所以測試肯定是通過的,但這個測試也是個無效的測試。

Assert

Assert做什麼?Assert基於程式碼的返回值、物件的最終狀態、事件是否發生等情況來評估測試的結果。Assert的結果可能是Pass或者Fail。如果所有的asserts都pass了,那麼整個測試就pass了;如果有任何assert fail了,那麼測試就fail了。

xUnit提供了以下型別的Assert:

  • boolean:True/False
  • String:相等/不等,是否為空,以..開始/結束,是否包含子字串,匹配正則表示式
  • 數值型:相等/不等,是否在某個範圍內,浮點的精度
  • Collection:內容是否相等,是否包含某個元素,是否包含滿足某種條件(predicate)的元素,是否所有的元素都滿足某個assert
  • Raised events:Custom events,Framework events(例如:PropertyChanged)
  • Object Type:是否是某種型別,是否某種型別或繼承與某種型別

一個test裡應該有多少個asserts?

一種建議的做法是,每個test方法裡面只有一個assert。

而還有一種建議就是,每個test裡面可以有多個asserts,只要這些asserts都是針對同一個行為就行。

第一個Assert

目標類:

    public class Patient
    {
        public Patient()
        {
            IsNew = true;
        }

        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string FullName => $"{FirstName} {LastName}";
        public int HeartBeatRate { get; set; }
        public bool IsNew { get; set; }

        public void IncreaseHeartBeatRate()
        {
            HeartBeatRate = CalculateHeartBeatRate() + 2;
        }

        private int CalculateHeartBeatRate()
        {
            var random = new Random();
            return random.Next(1, 100);
        }
    }

測試類:

    public class PatientShould
    {
        [Fact]
        public void HaveHeartBeatWhenNew()
        {
            var patient = new Patient();

            Assert.True(patient.IsNew);
        }
    }

執行測試:

 

結果符合預期,測試通過。

改為Assert.False()的話:

測試Fail。

String Assert

測試string是否相等

        [Fact]
        public void CalculateFullName()
        {
            var p = new Patient
            {
                FirstName = "Nick",
                LastName = "Carter"
            };
            Assert.Equal("Nick Carter", p.FullName);
        }

然後你需要Build一下,這樣VS Test Explorer才能發現新的test。

執行測試,結果Pass:

同樣改一下Patient類(別忘了Build一下),讓結果失敗:

從失敗資訊可以看到期待值和實際值。

StartsWith, EndsWith

        [Fact]
        public void CalculateFullNameStartsWithFirstName()
        {
            var p = new Patient
            {
                FirstName = "Nick",
                LastName = "Carter"
            };
            Assert.StartsWith("Nick", p.FullName);
        }

        [Fact]
        public void CalculateFullNameEndsWithFirstName()
        {
            var p = new Patient
            {
                FirstName = "Nick",
                LastName = "Carter"
            };
            Assert.EndsWith("Carter", p.FullName);e);
        }

Build,然後Run Test,結果Pass:

忽略大小寫 ignoreCase

string預設的Assert是區分大小寫的,這樣就會失敗:

可以為這些方法新增一個引數ignoreCase設定為true,就會忽略大小寫:

包含子字串 Contains

        [Fact]
        public void CalculateFullNameSubstring()
        {
            var p = new Patient
            {
                FirstName = "Nick",
                LastName = "Carter"
            };
            Assert.Contains("ck Ca", p.FullName);
        }

Build,測試結果Pass。

正則表示式,Matches

測試一下First name和Last name的首字母是不是大寫的:

        [Fact]
        public void CalculcateFullNameWithTitleCase()
        {
            var p = new Patient
            {
                FirstName = "Nick",
                LastName = "Carter"
            };
            Assert.Matches("[A-Z]{1}{a-z}+ [A-Z]{1}[a-z]+", p.FullName);
        }

Build,測試通過。

數值 Assert

首先為Patient類新增一個property: BloodSugar。

    public class Patient
    {
        public Patient()
        {
            IsNew = true;
            _bloodSugar = 5.0f;
        }

        private float _bloodSugar;
        public float BloodSugar
        {
            get { return _bloodSugar; }
            set { _bloodSugar = value; }
        }
        ...

Equal:

        [Fact]
        public void BloodSugarStartWithDefaultValue()
        {
            var p = new Patient();
            Assert.Equal(5.0, p.BloodSugar);
        }

Build,測試通過。

範圍, InRange:

首先為Patient類新增一個方法,病人吃飯之後血糖升高:

        public void HaveDinner()
        {
            var random = new Random();
            _bloodSugar += (float)random.Next(1, 1000) / 100; //  應該是1000
        }

新增test:

        [Fact]
        public void BloodSugarIncreaseAfterDinner()
        {
            var p = new Patient();
            p.HaveDinner();
            // Assert.InRange<float>(p.BloodSugar, 5, 6);
            Assert.InRange(p.BloodSugar, 5, 6);
        }

Build,Run Test,結果Fail:

可以看到期待的Range和實際的值,這樣很好。如果你使用Assert.True(xx >= 5 && xx <= 6)的話,錯誤資訊只能顯示True或者False。

因為HaveDinner方法裡,表示式的分母應該是1000,修改後,Build,Run,測試Pass。

相關推薦

使用xUnit.net core程式進行單元測試(1)

導讀 為什麼要編寫自動化測試程式(Automated Tests)? 可以頻繁的進行測試 可以在任何時間進行測試,也可以按計劃定時進行,例如:可以在半夜進行自動測試。 肯定比人工測試要快。 可以更快速的發現錯誤。 基本上是非常可靠的。 測試程式碼與生產程式碼緊密結合。 使得開發團隊更具有幸

使用xUnit.net core程式進行單元測試(3)

測試的分組 開啟Game.Tests裡面的BossEnemyShould.cs, 為HaveCorrectPower方法新增一個Trait屬性標籤: [Fact] [Trait("Category", "Enemy")] public v

使用xUnit.net core程式進行單元測試(4)

資料驅動的測試 開啟PlayerCharacterShould.cs 新增幾個Fact測試方法: [Fact] public void TakeZeroDamage() { _sut.TakeDamage(

使用xUnit.net core程式進行單元測試 -- Assert

Assert Assert做什麼?Assert基於程式碼的返回值、物件的最終狀態、事件是否發生等情況來評估測試的結果。Assert的結果可能是Pass或者Fail。如果所有的asserts都pass了,那麼整個測試就pass了;如果有任何assert fail了,那麼測試就fail了。 xUnit提供

.NET Core: 在.NET Core進行單元測試

單元測試能夠幫助開發人員確保所開發的模組、類以及類中的方法等的正確性,在專案開發過程中,及時進行單元測試能夠避免不必要的BUG以及提高測試效率。 在本文中,我們會分別來學習如何使用MSTest、xUnit以及NUnit這些流行的.NET測試框架來對.NET Core專案進行測試。 一、專案建立 首先,建

好代碼是管出來的——.Net Core中的單元測試與代碼覆蓋率

情況 其它 netcore output 窗口 一個數據庫 過濾 and 令行   測試對於軟件來說,是保證其質量的一個重要過程,而測試又分為很多種,單元測試、集成測試、系統測試、壓力測試等等,不同的測試的測試粒度和測試目標也不同,如單元測試關註每一行代碼,集成測試關註的是

Spark程式進行單元測試-使用scala

Spark 中進行一些單元測試技巧: 最近剛寫了一點Spark上的單元測試,大概整理了一些 rdd測試 spark程式一般從叢集中讀取資料然後通過rdd進行轉換,這其中涉及到叢集,每次修改bug,

轉 使用NUnit在.Net程式設計中進行單元測試

引言: 舉一個可能會發生在你身邊的事件將更能貼近實際,幸好我們現在就有一件在程式設計師看來非常普通的任務: 你今天第一天上班,你的專案經理拿給你一疊不算厚的文件,告訴你今天的任務是按照文件中的要求編寫一個.Net類,可能因為任務並不複雜,所以他看上去非常的隨意。 今天能否很好的完成任務對你來說非常特殊,你拿

.NET Core 3.0 單元測試與 Asp.Net Core 3.0 整合測試

單元測試與整合測試 測試必要性說明 相信大家在看到單元測試與整合測試這個標題時,會有很多感慨,我們無數次的在實踐中提到要做單元測試、整合測試,但是大多數專案都沒有做或者僅建了專案檔案。這裡有客觀原因,已經接近交付日期了,我們沒時間做白盒測試了。也有主觀原因,面對業務複雜的程式碼我們不知道如何入手做單元測試,不

淺談.Net Core後端單元測試

- [1. 前言](#head1) - [2. 為什麼需要單元測試](#head2) - [2.1 防止迴歸](#head3) - [2.2 減少程式碼耦合](#head4) - [3. 基本原則和規範](#head5) - [3.1 3A原則](#head6) - [3.2 儘量避免直接測試私有方法

使用xunit對asp.net core webapi進行集成測試

rtu sharp task 技術 分離 bubuko 們的 this eba 新項目我們采用前後端分離,後端采用asp.net core webapi, 如何對後端代碼進行自動化測試呢,有以下幾種方案: 1. 單元測試,目前這個方案對我們來說難度很大,拋開時間的問題,單

ASP.NET Core 對Controller進行單元測試

單元測試對我們的程式碼質量非常重要。很多同學都會對業務邏輯或者工具方法寫測試用例,但是往往忽略了對Controller層寫單元測試。我所在的公司沒見過一個對Controller寫過測試的。今天來演示下如果對Controller進行單元測試。以下內容預設您對單元測試有所瞭解,比如如何mock一個介面。在這裡多叨

使用Docker ComposeASP.NET Core程式新增MySQL資料庫

本文翻譯自: Adding MySQL to ASP.NET Core App With Docker Compose           之前的例子中我們將程式進行容器化,本文我們會把MySQL資料庫作為另一個Container,用於程式的訪問。因為現

使用Xunit進行單元測試

row 自動安裝 net 必須 清除 版本 多次 重構 nbsp 使用Xunit進行單元測試 來源 https://www.cnblogs.com/ccccc05/archive/2017/08/01/7266914.html 目前在.Net框架下的測試工具主要有

讓現有vue前端專案快速支援多語言 - 用.net core程式快速替換中文資源Key,咱不幹體力活

前言 這是我第一次發部落格,2020年立個flag以後要經常發。 最近應公司上層要求,需要將現有專案儘快支援多語言,而中文內容可以找專業人員翻譯。那麼咱們說幹就幹,首先我們專案的前端是用vue寫的spa程式且元件方面用的element ui,那麼自然而然想到用vue官方推薦的vue i18n,我快速過了下i1

NUnit.Framework在VS2015中如何進行單元測試

開放 ron 微軟 strong 擴展 分享 方案 mar 項目 微軟在VS2015中加入了自動化生成測試功能, 在需要測試的源文件的公共方法中右鍵既可以創建單元測試。 不過需要註意的是,要在公共方法中創建,否則會提示這個錯誤 如下是自動化單元測試界面,可以發

在vue-cli生成的項目中使用karma+chrome進行單元測試

使用 設計實現 測試用例 runner 服務 進行 ui界面 包含 node 用vue-cli生成項目時,如果選擇了單元測試,那麽會采用karma+mocha作為單元測試框架,默認使用的瀏覽器是PhantomJs。 Karma是一個基於Node.js的JavaScri

springMVC整合Junit4進行單元測試

main方法 pri tail println test pan ati 測試的 tco 版權聲明:本文為博主原創文章,未經博主允許不得轉載。 用Junit做單元測試的好處多多,博主領悟到了兩點。一是不用在每個類裏面都寫main方法然後去測試;二是可以得到每個方法執行

Dora.Interception,.NET Core度身打造的AOP框架:全新的版本

分享 ide 1.0 nuget hub tex 普通 inb .class Dora.Interception 1.0(Github地址:可以訪問GitHub地址:https://github.com/jiangjinnan/Dora)推出有一段時間了,最近花了點時間將它

Glib 對 C 函數進行單元測試

error ati 完成 structure 是否 pac str txt b- 1. Glib 單元測試框架 Glib 為單元測試提供了一套完整的測試框架,每個測試運行包括以下幾個部分 測試數據結構 測試 setup 與 teardown 函數 測試函數 2. 單元測