昨天练习测试专案预设的元件後,今天要来测试之前所开发的Todolist app
来回忆一下Todolist的样子
这个Todolist我们要测试的情境有以下6个:
那我们就开始吧
新增Nunit测试专案并将bUnit套件安装好,新增TodoTests类别
[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);
}
[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);
}
输入框没有值这件事,可以再分成没有输入或输入空白字串,因此同样的测试程序码,可以用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! 空白字串的测试没过
来确认一下元件的Add程序码
void Add()
{
if (!string.IsNullOrEmpty(newTodoItem))
{
TodoList.Add(newTodoItem);
newTodoItem = "";
}
}
由於空白字串对於string.IsNullOrEmpty方法来说是false,所以符合条件进行Todolist的新增动作,因此我们可以将string.IsNullOrEmpty改为String.IsNullOrWhiteSpace,就可以通过测试罗
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);
}
测试都通过罗~
今天的文章要介绍的是Bucket Aggregations的一种聚合方式,其实Metrics Agg...
前言 昨天的文章带到 Reactstrap 的 Grid 写法, 不过当然不只有 <Conta...
前言 我们在实作中学会如何建立工作表与仪表板,并在仪表板中让多个工作表可以连动,使资料呈现方式多样化...
注:本文同步刊载在Medium,若习惯Medium的话亦可去那边看呦! 因为按照惯例,第三十天主要会...
高级管理层是最终负责的後果和底线。但是,活动和任务是根据某些标准(例如,RACI矩阵,负责,负责,谘...