使用 LeetCode 771 練習測試
題目大致上就是有個變數 J 跟 S,輸出在S 與 J 匹配的字元數量。(且 J 不會重覆字元)
所以
- J = “aA” , S = “aAAbbbb” 輸出為 3
- J = “z” , S = “ZZ” 輸出為 0
建立一個 Unit Test 專案 命名為 : LeetCode771JewelsAndStonesTests
Unit Test 的 3A 原則
- Arrange – 初始化
- Act – 執行
- Actual – 驗證結果
建立第一個測試 :
[TestMethod] public void NumJewelsInStonesTest_When_J_Is_aA_And_S_Is_aAAbbbb_Should_Be_3() { //Arrange var solution = new Solution(); var J = "aA"; var S = "aAAbbbb"; //Act var actual = solution.NumJewelsInStones(J, S); //Assert var expected = 3; Assert.AreEqual(expected, actual); }
產生空的 Solution.cs :
public class Solution { public int NumJewelsInStones(string J, string S) { throw new System.NotImplementedException(); } }
撰寫程式碼,通過測試 :
public class Solution { public int NumJewelsInStones(string J, string S) { int count = 0; var js = J.ToArray(); var ss = S.ToArray(); foreach (var j in js) { foreach (var s in ss) { if (j == s) { count++; } } } return count; } }
建立第二個測試 :
[TestMethod] public void NumJewelsInStonesTest_When_J_Is_z_And_S_Is_ZZ_Should_Be_0() { //Arrange var solution = new Solution(); var J = "z"; var S = "ZZ"; //Act var actual = solution.NumJewelsInStones(J, S); //Assert var expected = 0; Assert.AreEqual(expected, actual); }
由於可以直接通過測試 可以執行 Ctrl + RT (當前測試) 或 Ctrl + RA (所有測試)
安裝 Specflow
需先安裝 Visual Studio Extension (需重新啟動 Visual Studio)
Nuget 安裝 Specflow
建立 SpecflowFeature
專案,按右鍵,新增檔案
修改 Scenario :
Feature: Jewels and Stones @mytag Scenario: NumJewelsInStones Given I have entered J aA into the solution And I have entered S aAAbbbb into the solution When I press NumJewelsInStones Then the result should be 3 on the screen
右鍵產生 Steps
會新增一個 JewelsAndStonesSteps.cs
但你會發現變數並沒有帶入,所以要手動把它修改成 (.*) 跟傳入參數
回到 feature 會看到變數已有運作 :
直接建置的話會出現找不到 NUnit
因預設使用 NUnit 但這邊使用 MSTest 所以修正 App.config 使用 MsTest
<unitTestProvider name="MsTest" />
測試會顯示出來,此時已可以建置或執行測試 :
Specflow 的 JewelsAndStonesSteps.cs 程式部分 :
步驟跟 Unit Test 一樣,只是需要先用 ScenarioContext.Current.Add(key,value) 把值存起來
跟 ScenarioContext.Current.Get<type>(key) 取值 :
public class JewelsAndStonesSteps { [Given(@"I have entered J (.*) into the solution")] public void GivenIHaveEnteredJIntoTheSolution(string J) { ScenarioContext.Current.Add("J",J); } [Given(@"I have entered S (.*) into the solution")] public void GivenIHaveEnteredSIntoTheSolution(string S) { ScenarioContext.Current.Add("S", S); } [When(@"I press NumJewelsInStones")] public void WhenIPressNumJewelsInStones() { var solution = new Solution(); var J = ScenarioContext.Current.Get<string>("J"); var S = ScenarioContext.Current.Get<string>("S"); var actual = solution.NumJewelsInStones(J, S); ScenarioContext.Current.Add("actual", actual); } [Then(@"the result should be (.*) on the screen")] public void ThenTheResultShouldBeOnTheScreen(int expected) { var actual = ScenarioContext.Current.Get<int>("actual"); Assert.AreEqual(expected, actual); } }
完成測試後,需要建立第二個測試,由於步驟都跟第一個步驟完全相同,所以可以將 Scenario 轉成 Scenario Outline ,並建立 Examples
Scenario Outline: NumJewelsInStones Given I have entered J <J> into the solution And I have entered S <S> into the solution When I press NumJewelsInStones Then the result should be <result> on the screen Examples: | J | S | result | | aA | aAAbbbb | 3 | | z | ZZ | 0 |
最後,執行測試 :