NUnit - 測試案例 TestCaseAttribute

-- Pageviews

NUnit - 測試案例 TestCaseAttribute

本篇將介紹 NUnit 的 TestCaseAttribute,簡化測試案例的程式碼。

TestAttribute

在寫 NUnit 單一測試案例的時候,通常都是用 TestAttribute,如下:

1
2
3
4
5
6
7
8
9
10
11
[TestFixture]
public class MemberBLLTests
{
// ...

[Test]
public void ChangePassword_Success()
{
// ...
}
}

延伸上述程式碼,如果要對 ChangePassword 這個動做增加不同的測試案例,用 TestAttribute 的方式就要建立多個 Test Method。如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// ...

[Test]
public void ChangePassword_Same_Password()
{
// Arrange
var expected = false;
var loginName = "johnwu";
var oldPassword = "pass.123";
var newPassword = "pass.123";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_Old_Password_Too_Short()
{
// Arrange
var expected = false;
var loginName = "johnwu";
var oldPassword = "pass";
var newPassword = "pass.123";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_Old_Password_Too_Long()
{
// Arrange
var expected = false;
var loginName = "johnwu";
var oldPassword = "01234567890123456789a";
var newPassword = "pass.123";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_New_Password_Too_Short()
{
// Arrange
var expected = false;
var loginName = "johnwu";
var oldPassword = "pass.123";
var newPassword = "pass";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_New_Password_Too_Long()
{
// Arrange
var expected = false;
var loginName = "johnwu";
var oldPassword = "pass.123";
var newPassword = "01234567890123456789a";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_LoginName_Too_Short()
{
// Arrange
var expected = false;
var loginName = "john";
var oldPassword = "pass.123";
var newPassword = "pass.1234";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_LoginName_Too_Long()
{
// Arrange
var expected = false;
var loginName = "01234567890123456789a";
var oldPassword = "pass.123";
var newPassword = "pass.1234";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

[Test]
public void ChangePassword_LoginName_Incorrect_Format()
{
// Arrange
var expected = false;
var loginName = "john.wu";
var oldPassword = "pass.123";
var newPassword = "pass.1234";

// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
Assert.AreEqual(expected, actual);
}

看起來非常的累贅,每個測試方法除了 Method Name 不一樣之外,就只有 Arrange 不同。

TestCaseAttribute

NUnit 可以透過 TestCaseAttribute 把測試的參數傳入到測試方法,在 TestCaseAttribute 帶入 object 型態的陣列,該陣列的內容會依照索引傳入到測試方法,如下: NUnit - 測試案例 TestCaseAttribute

範例程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[TestCase(new object[] { "johnwu", "pass.123", "pass.1234" }, 
ExpectedResult = true, TestName = "ChangePassword_Success")]
[TestCase(new object[] { "johnwu", "pass.123", "pass.123" },
ExpectedResult = false, TestName = "ChangePassword_Same_Password")]
[TestCase(new object[] { "johnwu", "pass", "pass.123" },
ExpectedResult = false, TestName = "ChangePassword_Old_Password_Too_Short")]
[TestCase(new object[] { "johnwu", "01234567890123456789a", "pass.123" },
ExpectedResult = false, TestName = "ChangePassword_Old_Password_Too_Long")]
[TestCase(new object[] { "johnwu", "pass.123", "pass" },
ExpectedResult = false, TestName = "ChangePassword_New_Password_Too_Short")]
[TestCase(new object[] { "johnwu", "pass.123", "01234567890123456789a" },
ExpectedResult = false, TestName = "ChangePassword_New_Password_Too_Long")]
[TestCase(new object[] { "john", "pass.123", "pass.1234" },
ExpectedResult = false, TestName = "ChangePassword_LoginName_Too_Short")]
[TestCase(new object[] { "01234567890123456789a", "pass.123", "pass.1234" },
ExpectedResult = false, TestName = "ChangePassword_LoginName_Too_Long")]
[TestCase(new object[] { "john.wu", "pass.123", "pass.1234" },
ExpectedResult = false, TestName = "ChangePassword_LoginName_Incorrect_Format")]
public bool ChangePassword(string loginName, string oldPassword, string newPassword)
{
// Act
var actual = _memberBLL.ChangePassword(loginName, oldPassword, newPassword);

// Assert
return actual;
}

當有多個測試案例的時候,用 TestCaseAttribute 就會比 TestAttribute 還要簡潔很多。
但 TestCaseAttribute 有個缺點,參數只能只使用基本型別,不能動態產生物件。
如果測試案例的參數比較複雜,要改用 TestCaseSourceAttribute