您的位置:首页 > 其它

测试语法之断言介绍(三)(转)

2009-11-05 14:38 417 查看

概述

在测试框架中,断言是单元测试的核心,我们在测试中要对其程序断言,如果某个断言失败,方法的调用不会返回值,并且会报告一个错误。如果一个测试包含多个断言,那些紧跟失败断言的那些断言都不会执行,因此每个测试方法最好只有一个断言。

下面看看NUnit框架吧,来2张图:







断言

现在,我们使用经典的NUnit框架的最新版本,可以用三种方法来写我们的断言:

标准模式:过去比较经典的写法。这些方法在NUnit.Framework命名空间下的Assert类中以静态方法提供,对其不同的类型(字符串、集合、文件)NUnit.Framework框架还提供了字符串断言、集合断言、文件断言。
约束模式:全新的写法,使用Assert.That()方法来约束扩展所有的断言,使用新增NUnit.Framework.SyntaxHelpers命名空间下提供的方法调用NUnit.Framework.Constraints命名空间下的各种约束。
继承模式:只要把测试的类继承NUnit.Framework.AssertionHelper类,可以使用Expect()方法来替换Assert.That()方法。

在这里,我把Assert方法分为:同等断言、一致性断言、比较断言、类型断言、条件测试、工具方法这6类,另外还有字符串断言、集合断言、文件断言。

当然按照约束方式,也可以大致分为Equal Constraint、Same As Constraint、Condition Constraints、Comparison Constraints、Type Constraints、String Constraints、Collection Constraints、Property Constraint、Compound Constraints、Custom Constraints、List Mapper等。

下面我依次介绍一下断言,使用三种方式来写自己的断言。

Equality Asserts(同等断言)
Identity Asserts(一致性断言)
Comparison Asserts(比较断言)
Type Asserts(类型断言)
Condition tests(条件测试)
Utility methods(工具方法)
StringAssert(字符串断言)
CollectionAssert(集合断言)
FileAssert(文件断言)
其他约束

1.Equality Asserts、Equal Constraint

NUnit.Framework提供了Assert.AreEqual()、Assert.AreNotEqual()方法测试两个对象是否相等。方法支持相同类型,不同类型,多维数组,嵌套数组,集合类相互比较。

NUnit.Framework.AssertionHelper命名空间下提供了Is.EqualTo(object)方法使用同等约束条件来测试两个对象是否相等。当然了,我们继承NUnit.Framework.AssertionHelper类,可以使用Expect()方法来替换Assert.That()方法。下面给出这个例子:

注意:需要引用NUnit.Framework,NUnit.Framework.AssertionHelper,NUnit.Framework.Constraints命名空间,并把测试类继承AssertionHelper。

[Test]
public void EqualTest()
{
//定义一些变量
var i3 = new int[] { 1, 2, 3 };
var d3 = new double[] { 1.0, 2.0, 3.0 };
var iunequal = new int[] { 1, 3, 2 };
var array2x2 = new int[,] { { 1, 2 }, { 3, 4 } };
var array4 = new int[] { 1, 2, 3, 4 };
var actual = new string[] { "HELLO", "world" };
var expected = new string[] { "Hello", "World" };
//经典语法
Assert.AreEqual(4, 2 + 2);
Assert.AreEqual(i3, d3);
Assert.AreNotEqual(5, 2 + 2);
Assert.AreNotEqual(i3, iunequal);
//约束语法
Assert.That(2 + 2, Is.EqualTo(4));
Assert.That(2 + 2 == 4);
Assert.That(2 + 2, Is.Not.EqualTo(5));
Assert.That(2 + 2 != 5);
Assert.That(5.0, Is.EqualTo(5));
Assert.That(2.1 + 1.2, Is.EqualTo(3.3).Within(.0005));
Assert.That(double.PositiveInfinity, Is.EqualTo(double.PositiveInfinity));
Assert.That(double.NaN, Is.EqualTo(double.NaN));
Assert.That(i3, Is.EqualTo(d3));
Assert.That(i3, Is.Not.EqualTo(iunequal));
Assert.That(array2x2, Is.EqualTo(array4).AsCollection); //成功
Assert.That("Hello!", Is.EqualTo("HELLO!").IgnoreCase);
Assert.That(actual, Is.EqualTo(expected).IgnoreCase);
//使用继承语法
Expect(2 + 2, EqualTo(4));
Expect(2 + 2 == 4);
Expect(i3, EqualTo(d3));
Expect(2 + 2, Not.EqualTo(5));
Expect(i3, Not.EqualTo(iunequal));
}

2.Identity Asserts、Same As Constraint

Assert.AreSame()和Assert.AreNotSame()方法测试两个对象是否是同一个对象。Assert.Contains方法用来测试在一个数组或列表里是否包含该对象。

NUnit.Framework.AssertionHelper命名空间下提供了Is.SameAs(object)方法使用Same As约束条件来测试两个对象是否是相同对象。使用继承也是如此。

[Test]
public void SameAsTest()
{
//定义变量
var ex1 = new Exception();
var ex2 = ex1;
var ex3 = new Exception();
//约束语法
Assert.That(ex2, Is.SameAs(ex1));
Assert.That(ex3, Is.Not.SameAs(ex1));
//使用继承语法
Expect(ex2, SameAs(ex1));
Expect(ex3, Not.SameAs(ex1));
}

3.Comparison Asserts、Comparison Constraints

NUnit.Framework框架为我们提供了下面四个方法:

Assert.Greater(x, y)方法用于测试一个对象是否大于另外一个对象。
Assert.GreaterOrEqual(x, y)方法用于测试一个对象是否大于等于另外一个对象。
Assert.Less(x, y)方法用于测试一个对象是否小于另外一个对象。
Assert.LessOrEqual(x, y)方法用于测试一个对象是否小于等于另外一个对象。

NUnit.Framework.AssertionHelper命名空间下提供了Is.GreaterThan(IComparable)、Is.GreaterThanOrEqualTo(IComparable)、Is.AtLeast(IComparable)、 Is.LessThan(IComparable)、Is.LessThanOrEqualTo(IComparable)、Is.AtMost(IComparable)方法使用比较约束条件来测试比较两个对象。使用继承也是如此。

[Test]
public void ComparisonTest()
{
//经典语法
Assert.Greater(7, 3);
Assert.GreaterOrEqual(7, 3);
Assert.GreaterOrEqual(7, 7);
Assert.Less(3, 7);
Assert.LessOrEqual(3, 7);
Assert.LessOrEqual(3, 3);
//约束语法
Assert.That(7, Is.GreaterThan(3));
Assert.That(7, Is.GreaterThanOrEqualTo(3));
Assert.That(7, Is.AtLeast(3));
Assert.That(7, Is.GreaterThanOrEqualTo(7));
Assert.That(7, Is.AtLeast(7));
Assert.That(3, Is.LessThan(7));
Assert.That(3, Is.LessThanOrEqualTo(7));
Assert.That(3, Is.AtMost(7));
Assert.That(3, Is.LessThanOrEqualTo(3));
Assert.That(3, Is.AtMost(3));
//使用继承语法
Expect(7, GreaterThan(3));
Expect(7, GreaterThanOrEqualTo(3));
Expect(7, AtLeast(3));
Expect(7, GreaterThanOrEqualTo(7));
Expect(7, AtLeast(7));
Expect(3, LessThan(7));
Expect(3, LessThanOrEqualTo(7));
Expect(3, AtMost(7));
Expect(3, LessThanOrEqualTo(3));
Expect(3, AtMost(3));
}

4.Type Asserts、Type Constraints

Assert.IsAssignableFrom(),Assert.IsNotAssignableFrom(),Assert.IsInstanceOfType(),Assert.IsNotInstanceOfType()方法让我们可以构造一些关于对象类型的断言。

同理,NUnit.Framework.AssertionHelper命名空间下提供了Is.TypeOf(Type)、Is.InstanceOfType(Type)、Is.AssignableFrom(Type)方法使用类型约束条件来测试对象类型。使用继承也是如此。

[Test]
public void TypeTest()
{
//经典语法
Assert.AreEqual(typeof(string), "Hello".GetType());
Assert.AreEqual("System.String", "Hello".GetType().FullName);
Assert.AreNotEqual(typeof(int), "Hello".GetType());
Assert.AreNotEqual("System.Int32", "Hello".GetType().FullName);
Assert.IsInstanceOfType(typeof(string), "Hello");
Assert.IsNotInstanceOfType(typeof(string), 5);
Assert.IsAssignableFrom(typeof(string), "Hello");
Assert.IsNotAssignableFrom(typeof(string), 5);
//约束语法
Assert.That("Hello", Is.TypeOf(typeof(string)));
Assert.That("Hello", Is.Not.TypeOf(typeof(int)));
Assert.That("Hello", Is.InstanceOfType(typeof(string)));
Assert.That(5, Is.Not.InstanceOfType(typeof(string)));
Assert.That("Hello", Is.AssignableFrom(typeof(string)));
Assert.That(5, Is.Not.AssignableFrom(typeof(string)));
//使用继承语法
Expect("Hello", TypeOf(typeof(string)));
Expect("Hello", Not.TypeOf(typeof(int)));
Expect("Hello", InstanceOfType(typeof(string)));
Expect(5, Not.InstanceOfType(typeof(string)));
Expect("Hello", AssignableFrom(typeof(string)));
Expect(5, Not.AssignableFrom(typeof(string)));
}

5.Condition Tests、Condition Constraints

测试框架提供了Assert.IsTrue,Assert.IsFalse,Assert.IsNaN,Assert.IsEmpty、Assert.IsNotEmpty,Assert.IsNull、Assert.IsNotNull方法分别用于测试两个对象是否正确,错误,非数字,(字符串或集合)空、非空,引用为空、引用不为空。

而NUnit.Framework.AssertionHelper命名空间也提供相类似的方法使用条件约束测试对象。直接看例子:

[Test]
public void ConditionTest()
{
//定义变量
double d = double.NaN;
//经典语法
Assert.IsNull(null);
Assert.IsNotNull(42);
Assert.IsTrue(2 + 2 == 4);
Assert.IsFalse(2 + 2 == 5);
Assert.IsNaN(d);
Assert.IsEmpty("");
Assert.IsNotEmpty("Hello!");
Assert.IsEmpty(new bool[0]);
Assert.IsNotEmpty(new int[] { 1, 2, 3 });
//约束语法
Assert.That(null, Is.Null);
Assert.That(42, Is.Not.Null);
Assert.That(2 + 2 == 4, Is.True);
Assert.That(2 + 2 == 4);
Assert.That(2 + 2 == 5, Is.False);
Assert.That(d, Is.NaN);
Assert.That("", Is.Empty);
Assert.That("Hello!", Is.Not.Empty);
Assert.That(new bool[0], Is.Empty);
Assert.That(new int[] { 1, 2, 3 }, Is.Not.Empty);
//使用继承语法
Expect(null, Null);
Expect(42, Not.Null);
Expect(2 + 2 == 4, True);
Expect(2 + 2 == 4);
Expect(2 + 2 == 5, False);
Expect(d, NaN);
Expect("", Empty);
Expect("Hello!", Not.Empty);
Expect(new bool[0], Empty);
Expect(new int[] { 1, 2, 3 }, Not.Empty);
}

6.Utility methods

我们想对测试有自定义控制,测试框架提供了两个实用方法:Assert.Fail()和Assert.Ignore()方法。这对于开发你自己的特定项目的断言,例如用于判断中它非常有用。

Assert.Fail()方法表示这个测试方法是一个失败方法,这个失败是基于其他方法没有封装的测试。

Assert.Ignore()方法表示这个测试方法是一个忽略的方法,在测试过程中,将忽略这个测试。

7.StringAssert、String Constraints

StringAssert类提供许多AreEqualIgnoringCase、Contains、StartsWith、EndsWith、IsMatch、Equals、ReferenceEquals方法,这些方法在检查字符串值时是有用的。

而NUnit.Framework.AssertionHelper命名空间也提供相类似的Text.Contains(string)、Text.DoesNotContain(string)、Text.StartsWith(string)、Text.DoesNotStartWith(string)、Text.EndsWith(string)、Text.DoesNotEndWith(string)、Text.Matches(string)、Text.DoesNotMatch(string) 方法使用字符串约束检查字符串。直接看例子:

[Test]
public void StringTest()
{
//定义变量
var phrase = "Hello World!";
var array = new string[] { "abc", "bad", "dba" };
var greetings = new string[] { "Hello!", "Hi!", "Hola!" };
var passage = "Now is the time for all good men to come to the aid of their country.";
var quotes = new string[] { "Never say never", "It's never too late", "Nevermore!" };
//经典语法
StringAssert.Contains("World", phrase);
StringAssert.StartsWith("Hello", phrase);
StringAssert.EndsWith("!", phrase);
StringAssert.AreEqualIgnoringCase("hello world!", phrase);
StringAssert.IsMatch("all good men", passage);
StringAssert.IsMatch("Now.*come", passage);
//约束语法
//测试是否包含"World"
Assert.That(phrase, Text.Contains("World"));
Assert.That(phrase, Text.DoesNotContain("goodbye"));
Assert.That(phrase, Text.Contains("WORLD").IgnoreCase);
Assert.That(phrase, Text.DoesNotContain("BYE").IgnoreCase);
Assert.That(array, Text.All.Contains("b"));
//测试字符串是否以"Hello"开始
Assert.That(phrase, Text.StartsWith("Hello"));
Assert.That(phrase, Text.DoesNotStartWith("Hi!"));
Assert.That(phrase, Text.StartsWith("HeLLo").IgnoreCase);
Assert.That(phrase, Text.DoesNotStartWith("HI").IgnoreCase);
Assert.That(greetings, Text.All.StartsWith("h").IgnoreCase);
//测试字符串是否以"!"结束
Assert.That(phrase, Text.EndsWith("!"));
Assert.That(phrase, Text.DoesNotEndWith("?"));
Assert.That(phrase, Text.EndsWith("WORLD!").IgnoreCase);
Assert.That(greetings, Text.All.EndsWith("!"));
Assert.That(phrase, Is.EqualTo("hello world!").IgnoreCase);
Assert.That(phrase, Is.Not.EqualTo("goodbye world!").IgnoreCase);
Assert.That(new string[] { "Hello", "World" },
Is.EqualTo(new object[] { "HELLO", "WORLD" }).IgnoreCase);
Assert.That(new string[] { "HELLO", "Hello", "hello" },
Is.All.EqualTo("hello").IgnoreCase);
//测试字符串是否同"all good men"相配
Assert.That(passage, Text.Matches("all good men"));
Assert.That(passage, Text.Matches("Now.*come"));
Assert.That(passage, Text.DoesNotMatch("all.*men.*good"));
Assert.That(passage, Text.Matches("ALL").IgnoreCase);
Assert.That(quotes, Text.All.Matches("never").IgnoreCase);
//使用继承语法
//测试是否包含"World"
Expect(phrase, Contains("World"));
Expect(phrase, Not.Contains("goodbye"));
Expect(phrase, Contains("WORLD").IgnoreCase);
Expect(phrase, Not.Contains("BYE").IgnoreCase);
Expect(array, All.Contains("b"));
//测试字符串是否以"Hello"开始
Expect(phrase, StartsWith("Hello"));
Expect(phrase, Not.StartsWith("Hi!"));
Expect(phrase, StartsWith("HeLLo").IgnoreCase);
Expect(phrase, Not.StartsWith("HI").IgnoreCase);
Expect(greetings, All.StartsWith("h").IgnoreCase);
//测试字符串是否以"!"结束
Expect(phrase, EndsWith("!"));
Expect(phrase, Not.EndsWith("?"));
Expect(phrase, EndsWith("WORLD!").IgnoreCase);
Expect(greetings, All.EndsWith("!"));
Expect(phrase, EqualTo("hello world!").IgnoreCase);
Expect(phrase, Not.EqualTo("goodbye world!").IgnoreCase);
Expect(new string[] { "Hello", "World" },
EqualTo(new object[] { "HELLO", "WORLD" }).IgnoreCase);
Expect(new string[] { "HELLO", "Hello", "hello" },
All.EqualTo("hello").IgnoreCase);
//测试字符串是否同"all good men"相配
Expect(passage, Matches("all good men"));
Expect(passage, Matches("Now.*come"));
Expect(passage, Not.Matches("all.*men.*good"));
Expect(passage, Matches("ALL").IgnoreCase);
Expect(quotes, All.Matches("never").IgnoreCase);
}

8.CollectionAssert、Collection Constraints

CollectionAssert类提供许多方法,像AllItemsAreInstancesOfType、AllItemsAreNotNull、AllItemsAreUnique、AreEqual(相同对象和次序)、AreEquivalent(相同对象次序不同)、AreNotEqual、AreNotEquivalent、Contains、DoesNotContain、IsEmpty、IsNotEmpty、IsNotSubsetOf、IsSubsetOf、ReferenceEquals。这些方法在检查集合值和比较两个集合时是有用的。集合参数必须实现IEnumerable接口。

而NUnit.Framework.AssertionHelper命名空间也提供相类似的方法使用集合约束检查集合。下面用例子说明,一看就明白。

[Test]
public void AllItemsTests()
{
//定义3个集合
object[] ints = new object[] { 1, 2, 3, 4 };
object[] doubles = new object[] { 0.99, 2.1, 3.0, 4.05 };
object[] strings = new object[] { "abc", "bad", "cab", "bad", "dad" };
//经典语法
CollectionAssert.AllItemsAreNotNull(ints);//ints集合所有项不为空
CollectionAssert.AllItemsAreInstancesOfType(ints, typeof(int));//ints集合所有项类型为int
CollectionAssert.AllItemsAreInstancesOfType(strings, typeof(string));
CollectionAssert.AllItemsAreUnique(ints);//ints集合所有项都是唯一的
//Helper语法
Assert.That(ints, Is.All.Not.Null);
Assert.That(ints, Has.None.Null);
Assert.That(ints, Is.All.InstanceOfType(typeof(int)));
Assert.That(ints, Has.All.InstanceOfType(typeof(int)));
Assert.That(strings, Is.All.InstanceOfType(typeof(string)));
Assert.That(strings, Has.All.InstanceOfType(typeof(string)));
Assert.That(ints, Is.Unique);
Assert.That(strings, Is.Not.Unique);
Assert.That(ints, Is.All.GreaterThan(0));
Assert.That(ints, Has.All.GreaterThan(0));
Assert.That(ints, Has.None.LessThanOrEqualTo(0));
Assert.That(strings, Text.All.Contains("a"));
Assert.That(strings, Has.All.Contains("a"));
Assert.That(strings, Has.Some.StartsWith("ba"));
Assert.That(strings, Has.Some.Property("Length", 3));
Assert.That(strings, Has.Some.StartsWith("BA").IgnoreCase);
Assert.That(doubles, Has.Some.EqualTo(1.0).Within(.05));
//使用继承语法
Expect(ints, All.Not.Null);
Expect(ints, None.Null);
Expect(ints, All.InstanceOfType(typeof(int)));
Expect(strings, All.InstanceOfType(typeof(string)));
Expect(ints, Unique);
Expect(strings, Not.Unique);
Expect(ints, All.GreaterThan(0));
Expect(ints, None.LessThanOrEqualTo(0));
Expect(strings, All.Contains("a"));
Expect(strings, Some.StartsWith("ba"));
Expect(strings, Some.StartsWith("BA").IgnoreCase);
Expect(doubles, Some.EqualTo(1.0).Within(.05));
}

9.FileAssert

FileAssert类提供AreEqual、AreNotEqual方法来比较两个文件,文件可以作为Stream、FileInfo、指定的文件路径来操作。

10.其他约束

这些约束都是新增的,由于和经典的断言没有一致的分类,我把它们单独列出来了,也在这里说说。

10-1.Property Constraint

属性约束。由主要测试对象的属性。

[Test]
public void PropertyTest()
{
//定义变量
string[] array = { "abc", "bca", "xyz", "qrs" };
string[] array2 = { "a", "ab", "abc" };
ArrayList list = new ArrayList(array);
//约束语法
Assert.That(list, Has.Property("Count"));//是否有Count属性
Assert.That(list, Has.No.Property("Length"));//是否没有Length属性
Assert.That("Hello", Has.Property("Length", 5));//"Hello"的Length属性是否是5
Assert.That("Hello", Has.Length(5));//"Hello"的Length属性是否是5
Assert.That("Hello", Has.Property("Length").EqualTo(5));//"Hello"的Length属性是否是5
Assert.That("Hello", Has.Property("Length").GreaterThan(3));//"Hello"的Length属性是否大于3
Assert.That(array, Has.Property("Length", 4));
Assert.That(array, Has.Length(4));
Assert.That(array, Has.Property("Length").LessThan(10));
Assert.That(array, Has.All.Property("Length", 3));//所有项Length属性是否是3
Assert.That(array, Has.All.Length(3));
Assert.That(array, Is.All.Length(3));
Assert.That(array, Has.All.Property("Length").EqualTo(3));
Assert.That(array, Is.All.Property("Length").EqualTo(3));
Assert.That(array2, Has.Some.Property("Length", 2));
Assert.That(array2, Has.Some.Length(2));
Assert.That(array2, Has.Some.Property("Length").GreaterThan(2));
Assert.That(array2, Is.Not.Property("Length", 4));
Assert.That(array2, Is.Not.Length(4));
Assert.That(array2, Has.No.Property("Length").GreaterThan(3));
Assert.That(List.Map(array2).Property("Length"), Is.EqualTo(new int[] { 1, 2, 3 }));
Assert.That(List.Map(array2).Property("Length"), Is.EquivalentTo(new int[] { 3, 2, 1 }));
Assert.That(List.Map(array2).Property("Length"), Is.SubsetOf(new int[] { 1, 2, 3, 4, 5 }));
Assert.That(List.Map(array2).Property("Length"), Is.Unique);
Assert.That(list, Has.Count(4));
//继承语法
Expect(list, Property("Count"));
Expect(list, Not.Property("Nada"));
Expect("Hello", Property("Length", 5));
Expect("Hello", Length(5));
Expect("Hello", Property("Length").EqualTo(5));
Expect("Hello", Property("Length").GreaterThan(0));
Expect(array, Property("Length", 4));
Expect(array, Length(4));
Expect(array, Property("Length").LessThan(10));
Expect(array, All.Property("Length", 3));
Expect(array, All.Length(3));
Expect(array, All.Property("Length").EqualTo(3));
Expect(array2, Some.Property("Length", 2));
Expect(array2, Some.Length(2));
Expect(array2, Some.Property("Length").GreaterThan(2));
Expect(array2, None.Property("Length", 4));
Expect(array2, None.Length(4));
Expect(array2, None.Property("Length").GreaterThan(3));
Expect(Map(array2).Property("Length"), EqualTo(new int[] { 1, 2, 3 }));
Expect(Map(array2).Property("Length"), EquivalentTo(new int[] { 3, 2, 1 }));
Expect(Map(array2).Property("Length"), SubsetOf(new int[] { 1, 2, 3, 4, 5 }));
Expect(Map(array2).Property("Length"), Unique);
Expect(list, Count(4));
}

10-2.Compound Constraints

进行对象间的比较。由几个方法复合作用。

[Test]
public void CompoundTest()
{
//约束语法
Assert.That(2 + 2, Is.Not.EqualTo(5));
Assert.That(new int[] { 1, 2, 3 }, Is.All.GreaterThan(0));
Assert.That(2.3, Is.GreaterThan(2.0) & Is.LessThan(3.0));
Assert.That(3, Is.LessThan(5) | Is.GreaterThan(10));
//继承语法
Expect(2 + 2, Not.EqualTo(5));
Expect(2.3, GreaterThan(2.0) & LessThan(3.0));
}

10-3.List Mapper

集合映射,比如下面的例子,测试strings数组对应项的Length属性是否为lengths对应项的值。

[Test]
public void ListMapperTest()
{
//定义2个数组
string[] strings = new string[] { "a", "ab", "abc" };
int[] lengths = new int[] { 1, 2, 3 };
//约束语法
Assert.That(List.Map(strings).Property("Length"),
Is.EqualTo(lengths));
Assert.That(new ListMapper(strings).Property("Length"),
Is.EqualTo(lengths));
//继承语法
Expect(Map(strings).Property("Length"), EqualTo(lengths));
}

结束语

关于这篇测试语法断言介绍,由于断言很多,很难在一篇文章中把所有的断言学习到。之前,我也想考虑分为经典模式和约束模式来介绍,发现大致相同,也浪费大量时间,所以千思万想,把这些属性整合在一起综合介绍,带着丰富的例子,相信可以掌握这些断言。考虑到本节代码过多,还有一部分还没有贴出来,提供下载。地址为:YJingLee.Test.zip(VS2008项目,如果你是VS2005只需复制其中的测试文件到你的项目中即可)

转自:/article/6948037.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: