iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 29
0
Modern Web

今晚,我想來點Blazor系列 第 29

Day 29:

昨天練習測試專案預設的元件後,今天要來測試之前所開發的Todolist app
來回憶一下Todolist的樣子

這個Todolist我們要測試的情境有以下6個:

  1. 顯示待辦清單且有2筆預設待辦事項
  2. 輸入框有值_點Add按鈕_待辦事項出現在待辦清單
  3. 輸入框有值_點Add按鈕_輸入框清空
  4. 輸入框沒有值_點Add按鈕_待辦清單沒有新增待辦事項
  5. 點擊刪除鈕並確定_可刪除待辦事項
  6. 點擊刪除鈕但取消_不會刪除待辦事項

那我們就開始吧

新增Nunit測試專案並將bUnit套件安裝好,新增TodoTests類別https://ithelp.ithome.com.tw/upload/images/20201013/20130058AfNPBI0kq0.png

第一個測試案例:顯示待辦清單且有2筆待辦事項

[Test]
        public void 顯示待辦清單且有2筆待辦事項()
        {
            //arrange
            var ctx = new Bunit.TestContext();

            //act
            var cut = ctx.RenderComponent<Index>();

            //assert
            string expectedHtml = @"<div>
                                  <table class='table table-hover'>
                                    <tbody>
                                      <tr>
                                        <th>待辦事項</th >
                                        <th> 刪除 </th >
                                      </tr >
                                      <tr>
                                        <td>Buy Milk</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>Buy Apple</td>
                                        <td>
                                          <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                                <div>
                                  <label>New Todo:</label>
                                  <input type='text'>
                                  <button class='btn btn-primary' id='AddBtn'>Add</button>
                                </div>
                                <br>";

            //與預期產生的html做比對
            cut.MarkupMatches(expectedHtml);
        }

第二個測試案例:輸入框有值_點Add按鈕_待辦事項出現在待辦清單

[Test]
        public void 輸入框有值_點Add按鈕_待辦事項出現在待辦清單()
        {
            var ctx = new Bunit.TestContext();

            var cut = ctx.RenderComponent<Index>();

            //在New Todo的input輸入框,輸入New Item
            cut.Find("input").Change("New Item");

            //點擊Add按鈕
            cut.Find("#AddBtn").Click();
          
            //預期的待辦清單將會多一個New Item
            string expectedHtml = @"<div>
                                  <table class='table table-hover'>
                                    <tbody>
                                      <tr>
                                        <th>待辦事項</th >
                                        <th> 刪除 </th >
                                      </tr >
                                      <tr>
                                        <td>Buy Milk</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>Buy Apple</td>
                                        <td>
                                          <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>New Item</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                                <div>
                                  <label>New Todo:</label>
                                  <input type='text' value=''>
                                  <button class='btn btn-primary' id='AddBtn'>Add</button>
                                </div>
                                <br>";
           
            cut.MarkupMatches(expectedHtml);
}

第三個測試案例:輸入框沒有值_點Add按鈕_待辦清單沒有新增待辦事項

輸入框沒有值這件事,可以再分成沒有輸入或輸入空白字串,因此同樣的測試程式碼,可以用NUnit框架的[TestCase]代入參數來進行:

[TestCase("")]
        [TestCase(" ")]
        public void 輸入框沒有值_點Add按鈕_待辦清單沒有新增待辦事項(string input)
        {
            var ctx = new Bunit.TestContext();

            var cut = ctx.RenderComponent<Index>();

            cut.Find("input").Change(input);
            cut.Find("#AddBtn").Click();

            string expectedHtml = @$"<div>
                                  <table class='table table-hover'>
                                    <tbody>
                                      <tr>
                                        <th>待辦事項</th >
                                        <th> 刪除 </th >
                                      </tr >
                                      <tr>
                                        <td>Buy Milk</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>Buy Apple</td>
                                        <td>
                                          <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                                <div>
                                  <label>New Todo:</label>
                                  <input type='text' value='{input}' >
                                  <button class='btn btn-primary' id='AddBtn'>Add</button>
                                </div>
                                <br>";

            cut.MarkupMatches(expectedHtml);
        }

執行測試之後,Oops! 空白字串的測試沒過
https://ithelp.ithome.com.tw/upload/images/20201013/201300581VJLQqSYVx.png

來確認一下元件的Add程式碼

void Add()
    {
        if (!string.IsNullOrEmpty(newTodoItem))
        {
            TodoList.Add(newTodoItem);
            newTodoItem = "";
        }
    }

由於空白字串對於string.IsNullOrEmpty方法來說是false,所以符合條件進行Todolist的新增動作,因此我們可以將string.IsNullOrEmpty改為String.IsNullOrWhiteSpace,就可以通過測試囉
https://ithelp.ithome.com.tw/upload/images/20201013/20130058kkFjRNFKzy.png

第四個測試案例:輸入框有值_點Add按鈕_輸入框清空

var ctx = new Bunit.TestContext();

            var cut = ctx.RenderComponent<Index>();

            cut.Find("input").Change("New Item");
            cut.Find("#AddBtn").Click();

            string expectedHtml = @"<div>
                                  <table class='table table-hover'>
                                    <tbody>
                                      <tr>
                                        <th>待辦事項</th >
                                        <th> 刪除 </th >
                                      </tr >
                                      <tr>
                                        <td>Buy Milk</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>Buy Apple</td>
                                        <td>
                                          <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>New Item</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                                <div>
                                  <label>New Todo:</label>
                                  <input type='text' value=''>
                                  <button class='btn btn-primary' id='AddBtn'>Add</button>
                                </div>
                                <br>";
            cut.MarkupMatches(expectedHtml);

第五個測試案例:點擊刪除鈕並確定_可刪除待辦事項

Todolist的刪除功能使用sweetalert這個套件,在元件中是使用IJSRuntime物件來進行javascript的呼叫,因此在測試程式碼這邊,也需要mock一個IJSRuntime物件,來設定sweetalert confirm的回傳值。

要mock IJSRuntime,可以用一般常看到的幾個知名mocking library,像是moq、NSubstitute等等,這邊我們就直接用bUnit中的mock,這邊我們就直接用bUnit中的AddMockJSRuntime來進行mock動作。

[Test]
        public void 點擊刪除鈕並確定_可刪除待辦事項()
        {
            var ctx = new Bunit.TestContext();
            
            //mock JSRuntime
            var mockJS = ctx.Services.AddMockJSRuntime();

            //設定SweetConfirm function回傳true
            mockJS.Setup<bool>("SweetConfirm", "Delete", $"確定要刪除Buy Milk?").SetResult(true);
           
            var cut = ctx.RenderComponent<Index>();
                        
            var firstDeleteButton = cut.FindAll("button").FirstOrDefault();
         
            //點擊第一個刪除按鈕
            firstDeleteButton.Click();

            string expectedHtml = @"<div>
                                  <table class='table table-hover'>
                                    <tbody>
                                      <tr>
                                        <th>待辦事項</th>
                                        <th>刪除</th>
                                      </tr>
                                      <tr>
                                        <td>Buy Apple</td>
                                        <td>
                                          <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                                <div>
                                  <label>New Todo:</label>
                                  <input type='text'>
                                  <button class='btn btn-primary' id='AddBtn'>Add</button>
                                </div>
                                <br>";

            cut.MarkupMatches(expectedHtml);
        }

第六個測試案例:點擊刪除鈕但取消_不會刪除待辦事項

[Test]
        public void 點擊刪除鈕但取消_不會刪除待辦事項()
        {
            var ctx = new Bunit.TestContext();
						
						//mock JSRuntime
            var mockJS = ctx.Services.AddMockJSRuntime();

            //設定SweetConfirm function回傳false
            mockJS.Setup<bool>("SweetConfirm", "Delete", $"確定要刪除Buy Milk?").SetResult(false);

            var cut = ctx.RenderComponent<Index>();

            var firstDeleteButton = cut.FindAll("button").FirstOrDefault();

            firstDeleteButton.Click();

            string expectedHtml = @"<div>
                                  <table class='table table-hover'>
                                    <tbody>
                                      <tr>
                                        <th>待辦事項</th>
                                        <th> 刪除 </th>
                                      </tr>
                                      <tr>
                                        <td>Buy Milk</td>
                                           <td>
                                             <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                      <tr>
                                        <td>Buy Apple</td>
                                        <td>
                                          <button class='btn btn-danger btn-sm' >delete</button>
                                        </td>
                                      </tr>
                                    </tbody>
                                  </table>
                                </div>
                                <div>
                                  <label>New Todo:</label>
                                  <input type='text'>
                                  <button class='btn btn-primary' id='AddBtn'>Add</button>
                                </div>
                                <br>";

            cut.MarkupMatches(expectedHtml);
        }

測試都通過囉~
https://ithelp.ithome.com.tw/upload/images/20201013/20130058tnNItXZr3p.png


上一篇
Day 28:元件的單元測試
下一篇
Day 30:Deploy To GitHub Pages
系列文
今晚,我想來點Blazor30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言