编写可维护的测试用例
立即解锁
发布时间: 2025-08-22 00:21:20 阅读量: 1 订阅数: 3 


单元测试的艺术:从入门到精通
### 编写可维护的测试用例
在软件开发中,编写可维护的测试用例至关重要。以下将详细探讨如何实现这一目标,包括方法的可见性、消除代码重复、合理使用 setup 方法以及确保测试隔离等方面。
#### 方法可见性与测试可维护性
将方法设为内部方法并非保证测试更具可维护性的良策,因为开发者仍可能觉得更改该方法较为容易。而将方法作为明确的公共契约公开,则能让可能更改它的开发者知晓该方法有实际的使用契约,不可随意破坏。
若使用 2012 年之前版本的 Visual Studio,可能有“Create Private Accessor”选项,这是 Visual Studio 生成的一个包装类,利用反射调用私有方法。但请不要使用此工具,它会生成难以维护和阅读的问题代码。实际上,除非别无选择,否则应避免任何声称能为你生成单元测试或与测试相关内容的工具。
移除方法也不是好选择,因为生产代码也会使用该方法,否则最初就无需编写测试。
#### 消除测试中的代码重复
单元测试中的代码重复对开发者的影响可能与生产代码中的重复一样严重,甚至更甚。测试代码应与生产代码一样遵循 DRY(Don't Repeat Yourself)原则。重复代码意味着当测试的某个方面发生变化时,需要更改更多代码。例如,更改构造函数或类的使用语义,可能会对包含大量重复代码的测试产生重大影响。
下面通过一个简单的测试示例来说明:
```csharp
public class LogAnalyzer
{
public bool IsValid(string fileName)
{
if (fileName.Length < 8)
{
return true;
}
return false;
}
}
[TestFixture]
public class LogAnalyzerTestsMaintainable
{
[Test]
public void IsValid_LengthBiggerThan8_IsFalse()
{
LogAnalyzer logan = new LogAnalyzer();
bool valid = logan.IsValid("123456789");
Assert.IsFalse(valid);
}
}
```
当为同一类添加另一个测试时,会出现代码重复问题:
```csharp
[Test]
public void IsValid_LengthBiggerThan8_IsFalse()
{
LogAnalyzer logan = new LogAnalyzer();
bool valid = logan.IsValid("123456789");
Assert.IsFalse(valid);
}
[Test]
public void IsValid_LengthSmallerThan8_IsTrue()
{
LogAnalyzer logan = new LogAnalyzer();
bool valid = logan.IsValid("1234567");
Assert.IsTrue(valid);
}
```
若 `LogAnalyzer` 的使用方式(语义)发生变化,这些测试将需要独立维护,增加了维护工作量。例如,当 `LogAnalyzer` 类需要初始化时:
```csharp
public class LogAnalyzer
{
private bool initialized = false;
public bool IsValid(string fileName)
{
if (!initialized)
{
throw new NotInitializedException(
"The analyzer.Initialize() method should be" +
"called before any other operation!");
}
if (fileName.Length < 8)
{
return true;
}
return false;
}
public void Initialize()
{
//initialization logic here
initialized = true;
}
}
```
上述两个测试都会失败,因为它们都忽略了调用 `Initialize()` 方法。为消除重复,可以采用以下两种方法:
##### 使用辅助方法消除重复
可以引入一个共享的工厂方法 `GetNewAnalyzer()` 来创建 `LogAnalyzer` 的默认实例,将 `Initialize()` 调用放在该方法中:
```csharp
[Test]
public void IsValid_LengthBiggerThan8_IsFalse()
{
LogAnalyzer logan = GetNewAnalyzer();
bool valid = logan.IsValid("123456789");
Assert.IsFalse(valid);
}
[Test]
public void IsValid_LengthSmallerThan8_IsTrue()
{
LogAnalyzer logan = GetNewAnalyzer();
bool valid = logan.IsValid("1234567");
Assert.IsTrue(valid);
}
private LogAnalyzer GetNewAnalyzer()
{
LogAnalyzer analyzer = new LogAnalyzer();
analyzer.Initialize();
return analyzer;
}
```
##### 使用 `[Setup]` 方法消除重复
也可以在 `Setup` 方法中初始化 `LogAnalyzer`:
```csharp
[SetUp]
public void Setup()
{
logan = new LogAnalyzer();
logan.Initialize();
}
private LogAnalyzer logan = null;
[Test]
public void IsValid_LengthBiggerThan8_IsFalse()
{
bool valid = logan.IsValid("123456789");
Assert.IsFalse(valid);
}
[Test]
public void IsValid_LengthSmallerThan8_IsTrue()
{
```
0
0
复制全文
相关推荐










