概述
在測試架構中,斷言是單元測試的核心,我們在測試中要對其程式斷言,如果某個斷言失敗,方法的調用不會傳回值,并且會報告一個錯誤。如果一個測試包含多個斷言,那些緊跟失敗斷言的那些斷言都不會執行,是以每個測試方法最好隻有一個斷言。
下面看看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隻需複制其中的測試檔案到你的項目中即可)
轉自:
http://www.cnblogs.com/lyj/archive/2008/09/07/1286372.html部落格園大道至簡
http://www.cnblogs.com/jams742003/轉載請注明:部落格園