目录
7.示例:自定义标签[FileDataSource]实现读取数据源进行用例测试
(2)自定义测试标签[FileDataSource(path:)]实现代码
-
TestFixture
标记包含测试的类。该类的特征:(1)必须是public,否则NUnit找不到它;(2)必须有缺省的构造函数,否则NUnit不会构造它;(3)构造函数没有任何副作用,因为NUnit经常多次构造它。
每个包含测试的类都必须如上用[Test Fixture] attribute标记。
[TestFixture]
public class Tests
{
}
-
Test
标记测试函数。该函数的特征:1)必须是public;(2)没有参数;(3)没有返回值。
[TestFixture]
public class Tests
{
[Test]
public void AddTwoNum()
{
int a = 1;
int b = 2;
int result= a + b;
Assert.AreEqual(result, 3);
}
}
-
TestCase
标记有参数的测试方法。下例中1,2分别为参数a和b的值。
[TestCase(1,2)]
public void AddTwoNum(int a, int b)
{
int result = a + b;
Assert.AreEqual(result, 3);
}
-
SetUp
标记函数,该函数在每个测试函数执行之前都要执行。一般是资源初始化函数。
-
TearDown
标记函数,该函数在每个测试函数执行之后都要执行。一般是资源清除函数。
[TestFixture]
public class Tests
{
private int a;
private int b;
private int result;
[SetUp]
public void Init()
{
a = 1;
b = 2;
}
[Test]
public void AddTwoNum()
{
result = a + b;
Assert.AreEqual(result, 3);
}
[Test]
public void MultiplyTwoNum()
{
result = a * b;
Assert.AreEqual(result, 2);
}
[TearDown]
public void Clear()
{
result = 0;
}
}
-
ExpectedException
期望在运行时抛出一个期望的异常,如果是,则测试通过,否则不通过。如除0时会抛出异常。
[Test]
[ExpectedException(typeof(DivideByZeroException))]
public void DivideByZero()
{
int zero = 0;
int infinity = a/zero;
Assert.Fail("Should have gotten an exception");
}
-
Ignore
运行时忽略的测试。Ignore属性可以附加到测试方法,也可以附加到整个测试类
[Test]
[Ignore("Method is ignored")]
public void MultiplyTwoNum()
{
result = a * b;
Assert.AreEqual(result, 2);
}
7.Category
将测试分类,便于按类别运行测试。
[Test]
[Category("Calculator")]
public void MultiplyTwoNum()
{
result = a * b;
Assert.AreEqual(result, 2);
}
-
Category
将测试分类,便于按类别运行测试。
标记一个测试方法或测试类。
指定测试的分类标签。它可以用于过滤测试的运行。
[Test]
[Category("Calculator")]
public void MultiplyTwoNum()
{
result = a * b;
Assert.AreEqual(result, 2);
}
-
Explicit
忽略一个测试类或测试方法,直到它们显式的选择执行。
[Test, Explicit]
public void MultiplyTwoNum()
{
result = a * b;
Assert.AreEqual(result, 2);
}
10.Maxtime
标记测试用例的最大执行时间,超时时报错但不取消测试。
[Test]
[MaxTime(100)]
public void AddTwoNum()
{
int a = 1;
int b = 2;
int result = a + b;
Assert.AreEqual(result, 3);
}
11.Timeout
标记测试用例的超时时间,超时中断测试。
[Test]
[Timeout(100)]
public void AddTwoNum()
{
int a = 1;
int b = 2;
int result = a + b;
Assert.AreEqual(result, 3);
}
12.Repeat
标记测试方法重复执行的次数。
[Test,Repeat(5)]
public void AddTwoNum()
{
int a = 1;
int b = 2;
int result = a + b;
Assert.AreEqual(result, 3);
}
13.Retry
标记一个测试方法,设置重试次数。如果测试失败,则会自动重试指定次数。
[Test] [Retry(3)] public void Divide_TwoNumbers_ReturnsCorrectQuotient() { // 测试方法的代码和断言 }
14.TestCaseSource
提供测试用例数据源
标记一个测试方法,指定使用提供的数据源进行参数化测试。可以使用不同的数据源来动态生成测试用例。
[TestCaseSource]
是 NUnit 中用于参数化测试的特性之一。它允许从静态字段、属性或方法中提供测试用例数据源。
使用 [TestCaseSource]
可以灵活地定义和传递测试用例数据,从而在不修改测试方法代码的情况下执行多组测试。可以从一个数据源中动态提供测试用例。
[Test] [TestCaseSource(nameof(GetTestData))] public void Multiply_TwoNumbers_ReturnsCorrectProduct(int a, int b, int expectedProduct) { // 测试方法的代码和断言 } private static IEnumerable<TestCaseData> GetTestData() { yield return new TestCaseData(2, 3, 6); yield return new TestCaseData(5, 5, 25); }
(1)使用静态字段作为数据源
private static readonly object[] TestCases = { new object[] { 2, 3, 5 }, // 正常情况下的加法 new object[] { -2, 3, 1 }, // 负数相加 new object[] { 0, 0, 0 }, // 零相加 // 其他测试用例... }; [Test] [TestCaseSource(nameof(TestCases))] public void AddTest(int a, int b, int expected) { int actual = Add(a, b); Assert.AreEqual(expected, actual); }
(2)使用静态属性作为数据源
private static IEnumerable TestCases => new[] { new TestCaseData(2, 3, 5), // 正常情况下的加法 new TestCaseData(-2, 3, 1), // 负数相加 new TestCaseData(0, 0, 0), // 零相加 // 其他测试用例... }; [Test] [TestCaseSource(nameof(TestCases))] public void AddTest(int a, int b, int expected) { int actual = Add(a, b); Assert.AreEqual(expected, actual); }
(3)使用静态方法作为数据源
private static IEnumerable TestCases() { yield return new TestCaseData(2, 3, 5); // 正常情况下的加法 yield return new TestCaseData(-2, 3, 1); // 负数相加 yield return new TestCaseData(0, 0, 0); // 零相加 // 其他测试用例... } [Test] [TestCaseSource(nameof(TestCases))] public void AddTest(int a, int b, int expected) { int actual = Add(a, b); Assert.AreEqual(expected, actual); }
注意事项:
-
测试用例数据源可以是
object[]
、IEnumerable
、IEnumerable<object>
、IEnumerable<TestCaseData>
等类型。 -
对于每个测试用例,需要使用
TestCaseData
类的实例进行封装,以提供输入参数和预期结果。 -
数据源名称可以是数据源字段、属性或方法的名称,可以使用
nameof
运算符避免硬编码。
通过使用 [TestCaseSource]
特性,可以简化测试用例的编写,同时提供更灵活的参数化测试能力。这样可以轻松地执行多组输入输出的测试,覆盖不同的场景和边界情况。
15.Parallelizable
标记并行
标记一个测试类,指示该类的测试方法可以并行运行。可以提高测试的执行速度。
[TestFixture] [Parallelizable] public class MathTests { // 测试方法和其他注解 }
16.Sequential
标记顺序
[TestFixture] [Sequential] public class MathTests { // 测试方法和其他注解 }
17.OneTimeSetUp
标记一次性初始
[OneTimeSetUp] public voidOneTimeSetup() { // 在整个测试过程开始之前执行的设置操作 }
18.OneTimeTearDown
标记一次性清理
[OneTimeTearDown] publicvoidOneTimeTearDown() { // 在整个测试过程结束之后执行的清理操作 }
19.TestOf
标记测试对象
[Test] [TestOf(typeof(MathUtils))] publicvoidAdd_TwoPositiveNumbers_ReturnsCorrectSum() { // 测试方法的代码和断言 }
20.Range
指定参数范围
[Test] publicvoidDivide_TwoNumbers_ReturnsCorrectQuotient( [Range(1, 10)] inta, [Range(1, 10)] intb) { // 测试方法的代码和断言 }
21.Random
指定参数随机
[Test] publicvoidMultiply_TwoRandomNumbers_ReturnsCorrectProduct( [Random(1, 10, 5)] inta, [Random(1, 10, 5)] intb) { // 测试方法的代码和断言 }
22.Values
指定参数
[Test] publicvoidSubtract_TwoNumbers_ReturnsCorrectDifference( [Values(10, 5, 2)] inta, [Values(2, 1, 1)] intb) { // 测试方法的代码和断言 }
23.[Values]和[TestCase]的区别
-
-
24.自定义测试标签【重要】
1.标记测试方法的优先级(Priority):
using System; namespace MyNamespace { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class PriorityAttribute : Attribute { public int Value { get; private set; } public PriorityAttribute(int value) { Value = value; } } }
using NUnit.Framework; using MyNamespace; [TestFixture] public class MyTestClass { [Test] [Priority(1)] // 设置优先级为 1 public void MyTestMethod() { // 测试逻辑 } }
2.标记测试方法的重要性(Importance):
using System; namespace MyNamespace { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class ImportanceAttribute : Attribute { public ImportanceLevel Level { get; private set; } public ImportanceAttribute(ImportanceLevel level) { Level = level; } } public enum ImportanceLevel { Low, Medium, High } }
using NUnit.Framework; using MyNamespace; [TestFixture] public class MyTestClass { [Test] [Importance(ImportanceLevel.High)] // 设置重要性为 High public void MyTestMethod() { // 测试逻辑 } }
3.标记测试类的功能模块(Module):
using System; namespace MyNamespace { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public class ModuleAttribute : Attribute { public string Name { get; private set; } public ModuleAttribute(string name) { Name = name; } } }
using NUnit.Framework; using MyNamespace; [Module("User Management")] // 标记测试类属于 "User Management" 模块 public class UserManagementTests { [Test] public void CreateUserTest() { // 测试逻辑 } }
4.标记测试方法的作者(Author):
using System; namespace MyNamespace { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class AuthorAttribute : Attribute { public string Name { get; private set; } public AuthorAttribute(string name) { Name = name; } } }
using NUnit.Framework; using MyNamespace; [TestFixture] public class MyTestClass { [Test] [Author("John Doe")] // 设置作者为 "John Doe" public void MyTestMethod() { // 测试逻辑 } }
5.标记测试方法的描述(Description):
using System; namespace MyNamespace { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class DescriptionAttribute : Attribute { public string Text { get; private set; } public DescriptionAttribute(string text) { Text = text; } } }
using NUnit.Framework; using MyNamespace; [TestFixture] public class MyTestClass { [Test] [Description("This test case verifies the login functionality.")] // 设置描述信息 public void LoginTest() { // 测试逻辑 } }
6.标记测试方法的数据源(DataSource):
using System; namespace MyNamespace { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class DataSourceAttribute : Attribute { public string SourceName { get; private set; } public DataSourceAttribute(string sourceName) { SourceName = sourceName; } } }
using NUnit.Framework; using MyNamespace; [TestFixture] public class MyTestClass { [Test] [DataSource("TestData.csv")] // 设置数据源为 "TestData.csv" public void DataDrivenTest() { // 测试逻辑 } }
7.示例:自定义标签[FileDataSource]实现读取数据源进行用例测试
(1)测试数据源文件
a b excepted 1,2,3 0,0,0 -1,-2,-3 -0,-1,-1 -010,-101,-111
(2)自定义测试标签[FileDataSource(path:)]实现代码
using System; using System.Collections.Generic; using System.IO; namespace MyNamespace { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public class FileDataSourceAttribute : Attribute { public string FilePath { get; private set; } public FileDataSourceAttribute(string filePath) { FilePath = filePath; } public IEnumerable<TestCaseData> GetTestCases() { List<TestCaseData> testCases = new List<TestCaseData>(); // 读取测试数据文件 string[] lines = File.ReadAllLines(FilePath); // 跳过第一行数据(标题行) for (int i = 1; i < lines.Length; i++) { string line = lines[i]; string[] values = line.Split(','); // 解析测试数据并添加到 TestCaseData 列表 if ( values.Length == 3 && int.TryParse(values[0], out int input1) && int.TryParse(values[1], out int input2) && int.TryParse(values[2], out int expectedOutput)) { TestCaseData testCase = new TestCaseData(input1, input2, expectedOutput); testCases.Add(testCase); } else { // 如果测试数据格式不正确,可以选择记录日志或抛出异常 throw new FormatException("Invalid test data format in the file."); } } return testCases; } } }
(3)测试类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using FileDataSourceAttribute = TestTagBulid.FileDataSourceAttribute; namespace TestTagBulid { [TestFixture] [Author("ZhangJincheng")] public class MyTestClass { [Test] [TestCaseSource(typeof(FileDataSourceAttribute), nameof(FileDataSourceAttribute.GetTestCases))] [FileDataSource(@"C:/MISATDecompile/TestTagBulid/TestData.csv")] public void DataDrivenTest(int input1, int input2, int expectedOutput) { // 执行测试逻辑,并使用断言验证结果是否符合预期 int actualOutput = SomeOperation(input1, input2); Assert.AreEqual(expectedOutput, actualOutput); } private int SomeOperation(int a, int b) { // 执行一些操作并返回结果 return a + b; } } }
(4)测试结果
-
————————————————
原文链接:https://blog.csdn.net/liyazhen2011/article/details/86139815