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


<<:  三十日目:JavaScript XHR 终ノ章 。

>>:  [Day28] Go Bot使用者注册

IT铁人第29天 Elasticsearch 使用python查询资料 Aggregations:Terms

今天的文章要介绍的是Bucket Aggregations的一种聚合方式,其实Metrics Agg...

[Day9] Reactstrap = Bootstrap in React,你看离 React 越来越近了吧

前言 昨天的文章带到 Reactstrap 的 Grid 写法, 不过当然不只有 <Conta...

[Day18] Tableau 轻松学 - Relationships 与 Joins

前言 我们在实作中学会如何建立工作表与仪表板,并在仪表板中让多个工作表可以连动,使资料呈现方式多样化...

[Day 29] 从零开始学Python - 打包安装PyInstaller:谁把谁的灵魂,装进谁的身体

注:本文同步刊载在Medium,若习惯Medium的话亦可去那边看呦! 因为按照惯例,第三十天主要会...

数据及系统所有者(data and system owner)

高级管理层是最终负责的後果和底线。但是,活动和任务是根据某些标准(例如,RACI矩阵,负责,负责,谘...