首先安装nunit,然后我们需要创建一个NUnit项目,通常情况下我们只需要添加对nunit.framework(对应的dll是unit.framework.dll)的引用就够了,最后在项目属性的调试-->启动操作-->启动外部程序(C:\Program Files (x86)\NUnit 2.6.3\bin\nunit-x86.exe)
Nunit每一个测试函数都可以独立运行,所以我们在调用目标函数之前先要初始化目标函数执行所需要的环境,如打开数据库连接、添加测试数据等等。当然最后如删除测试数据和关闭数据库连接等。
当然啦做为一个测试的类,这个类还有一些限制,首先必须是Public,否则NUnit看不到它的存在.它必须有一个缺省的构造函数,否则是NUnit不会构造它.构造函数应该没有任何副作用,因为NUnit在运行时经常会构造这个类多次。
NUnit的常用标记
这些都是可以用来作为类或者方法的属性,它们都是System.Attribute类的直接或间接子类:
Category | 用来将测试分类。这个在主界面可以看到Tests/Categories两个选项卡,如果给方法标记了Category属性就会在Categories选项卡中看得到。 |
Combinatorial | 用来将来测试时需要测试各种可能的组合 [Test, Combinatorial] public void MyTest(){} 测试时实际会测试6种情况:MyTest(1, "A")/MyTest(1, "B")/MyTest(2, "A")/MyTest(2, "B")/MyTest(3, "A")/MyTest(3, "B")。 |
Culture | 设置测试时的语言环境,这对我们测试一些语言敏感的场景下有用,比如DateTime.ToString()在不同语言环境下得到的字符串并不相同。 |
Description | 用于指定测试对应的描述,如果选择将测试结果生成XML文件,那么就会在XML文件中看到这些描述。 |
ExpectedException | 指出执行测试时将会抛出Exception。 |
Explicit | 如果测试的类或者方法使用此Attribute,那么在使用带GUI的NUnit测试时这个类或者方法必须在界面上选定才会被执行。 |
Explicit | 忽略某个测试类或者方法。 |
Maxtime | 测试方法最大执行的毫秒数,如果程序的执行时间超过指定数值,那么就会被认为测试失败。 |
Random | 用于指定如何随机生成参数来测试方法。如下面的代码: [Test] public void TestDemo1([Values(1, 2, 3)] int x,[Random(-10,10,2)] int y) { Assert.Greater(x + y, 0); } 表示方法TestDemo1会生成6个测试,1,2,3分别作为参数x的值与两次从-10到10之间的随机数y组成6次测试。 |
Range | 指定参数的方法,如下面的方法: [Test] public void TestDemo2([Range(0, 11, 4)] int x) { Assert.AreEqual(x%3,0); } 表示从0开始递增,步长为4,且不大于11。 |
Repeat | 将重复测试的次数。 |
RequiresMTA | 表示测试时需要多线程单元(multi-threaded apartment)。 |
RequiresSTA | 表示测试时需要单线程单元(single-threaded apartment)。 |
SetUp | 在每个测试方法开始之前执行的初始化操作。在NUnit 2.5之前要求每个类只能有一个带SetUp属性的实例方法,但在NUnit 2.5之后则没有次数和必须是实例方法的限制。 |
TearDown | 与SetUp的作用相反,是在每个测试方法执行结束之后执行的方法。在NUnit 2.5之前要求每个类只能有一个带SetUp属性的实例方法,但在NUnit 2.5之后则没有次数和必须是实例方法的限制。 |
Test | 用来标记需要测试的方法,在NUnit 2.5之前只能用于标记实例方法,在NUnit 2.5之后则可以用于标记静态方法。 |
TestCase | 标记方法具有参数并且提供了在测试时需要的参数。如下面的代码: [TestCase(12, 3, 4)] [TestCase(12, 2, 6)] [TestCase(12, 4, 3)] public void DivideTest(int n, int d, int q) { Assert.AreEqual(q, n / d); } 将会执行三次测试,相当于: [Test] public void DivideTest() { Assert.AreEqual(4,12/3); } [Test] public void DivideTest() { Assert.AreEqual(6,12/2); } [Test] public void DivideTest() { Assert.AreEqual(3,12/4); } |
Timeout | 标记被测试的方法最大的执行时间,如果超出标记的时间,则会被取消执行并且被标记为测试失败。 |
TestFixture | 标记一个类可能具有[Test]/[SetUp]/[TearDown]方法,但这个类不能是抽象类。 |
TestFixtureSetUp | 标记在类中所有测试方法执行之前执行的方法。在NUnit 2.5之前只能在类中将此标记最多使用于一个实例方法,在NUnit 2.5之后则可以标记多个方法,而且不限于实例方法还可以用于静态方法。 |
TestFixtureTearDown | 标记在类中所有测试方法执行之后再执行的方法。在NUnit 2.5之前只能在类中将此标记最多使用于一个实例方法,在NUnit 2.5之后则可以标记多个方法,而且不限于实例方法还可以用于静态方法。 |
Values | 标记作为测试方法的一系列的参数。前面的代码实例中就有用法实例。 |
Ignore | 属性可以附加到一个独立的测试方法,也可以附加到整个测试类(TestFixture).如果Ignore属性附加到TestFixture,所有在fixture的测试都被忽略. |
Test Suite | Test Suite是test case或其他test suite的集合. 合成(Composite),模式描述了test case和test suite之间的关系. 参考来自NUnit的关于Suite的代码 Suite Attribute namespace NUnit.Tests { using System; using NUnit.Framework;
public class AllTests { [Suite] public static TestSuite Suite { get { TestSuite suite = new TestSuite("All Tests"); suite.Add(new OneTestCase()); suite.Add(new Assemblies.AssemblyTests()); suite.Add(new AssertionTest()); return suite; } } } } |
ExpectedException | 这里是一个验证这个假设的测试.有的时候,我们知道某些操作会有异常出现,例如, 在实例中增加除法,某个操作被0除,抛出的异常和.NET文档描述的一样.参看以下源代码. [Test] [ExpectedException(typeof(DivideByZeroException))] public void DivideByZero() { int zero = 0; int infinity = a/zero; Assert.Fail("Should have gotten an exception"); } |
NUnit的断言(Assertions)
断言是所有基于xUnit单元测试系列的核心,NUnit通过NUnit.Framework.Assert类提供了丰富的断言。具体说来,NUnit总共提供了11个类别的断言,它们是:
Equality Asserts | 用于断言对象是否相等方面的断言,主要表现为两个方法的重载:Assert.AreEqual()和Assert.AreNotEqual()两种形式的重载,重载参数包括了常见的基本数值类型(int/float/double等)和引用类型(表现为使用object作为参数). |
Identity Asserts | 用于判断引用类型的对象是否是同一个引用的断言及断言对象是否存在于某个集合中,如Assert.AreSame、Assert.AreNotSame及Assert.Contains。 |
Condition Asserts | 用于某些条件的断言,如:Assert.IsTrue、Assert.True、Assert.IsFalse、Assert.False、Assert.IsNull、Assert.Null、Assert.IsNotNull、Assert.NotNull、Assert.IsNaN、Assert.IsEmpty及Assert.IsNotEmpty。 |
Comparisons Asserts | 用于数值及实现了IComparable接口的类型之间的断言,如Assert.Greater(大于)、Assert.GreaterOrEqual(大于或等于)、Assert.Less(小于)、Assert.LessOrEqual(小于或等于)。 |
Type Asserts | 用于类型之间的判断,比如判断某个实例是否是某一类型或者是从某个类型继承,如:Assert.IsInstanceOfType、Assert.IsNotInstanceOfType、Assert.IsAssignableFrom、Assert.IsNotAssignableFrom。 在NUnit 2.5之后就增加了泛型方法,如Assert.IsInstanceOf<T>、Assert.IsNotInstanceOf<T>、Assert.IsAssignableFrom<T>、Assert.IsNotAssignableFrom<T>。。 |
Exception Asserts | 有关异常方面的断言,如Assert.Throws/Assert.Throws<T>、Assert.DoesNotThrow、Assert.Catch/Assert.Catch<T>。 |
Utility Methods | 用于精确控制测试过程,总共有四个方法,分别是:Assert.Pass、Assert.Fail、Assert.Ignore、Assert.Inconclusive。Assert.Pass和Assert.Fail是相反的, 前者是表示将立即终止测试并将测试结果标识为成功通过测试,后者是立即终止测试并将测试结果标识为测试失败。Assert.Ignore表示忽略测试,这个标记可以用于标识测试方法或者测试的类。 |
StringAssert | 用于字符串方面的断言,提供的方法有StringAssert.Contains、StringAssert.StartsWith、StringAssert.EndsWith、StringAssert.AreEqualIgnoringCase及StringAssert.IsMatch。 |
CollectionAssert | 关于集合方面的断言,提供的方法有CollectionAssert.AllItemsAreInstancesOfType、CollectionAssert.AllItemsAreNotNull、CollectionAssert.AllItemsAreUnique、CollectionAssert.AreEqual、 CollectionAssert.AreEquivalent、CollectionAssert.AreNotEqual、CollectionAssert.AreNotEquivalent、CollectionAssert.Contains、CollectionAssert.DoesNotContain、CollectionAssert.IsSubsetOf、 CollectionAssert.IsNotSubsetOf、CollectionAssert.IsEmpty、CollectionAssert.IsNotEmpty和CollectionAssert.IsOrdered。 |
FileAssert | 用于文件相关的断言,主要提供两个方法:FileAssert.AreEqual和FileAssert.AreNotEqual。 |
DirectoryAssert | 用于文件夹的断言,提供的方法有:DirectoryAssert.AreEqual、DirectoryAssert.AreNotEqual、DirectoryAssert.IsEmpty、DirectoryAssert.IsNotEmpty、DirectoryAssert.IsWithin和DirectoryAssert.IsNotWithin。 |
1 //连接字符串 2 string conStr = System.Configuration.ConfigurationManager.ConnectionStrings["connection"].ConnectionString; 3 Read_And_BindValue read_value = new Read_And_BindValue(); 4 5 private string parameter1 { get; set; } 6 private string parameter2 { get; set; } 7 private string areaCode { get; set; } 8 private string xt { get; set; } 9 10 [Test] 11 public void GetParameters() 12 { 13 //D_Meter_Zp[] d_meter_zp = read_value.Getd_meter_zp().ToArray(); 14 //D_Lc_Equip[] d_lc_equip = read_value.GetD_Lc_Equip().ToArray(); 15 //D_It[] d_id = read_value.GetD_It().ToArray(); 16 //Hs_Yx_Jk[] hs_yx_jk = read_value.GetHs_Yx_Jk().ToArray(); 17 Dictionary<string, string> d_meter_zp = read_value.GetD_meter_zp();//获取在d_meter_zp表中的数据 18 // Dictionary<string, string> d_lc_equip = read_value.GetD_Lc_Equip(); 19 20 #region d_meter_zp 21 if (d_meter_zp.Count > 0) 22 { 23 //存储异常信息 24 List<string> exs = new List<string>(); 25 26 foreach (var i in d_meter_zp) 27 { 28 parameter1 = d_meter_zp["box_bar_code"]; 29 areaCode = d_meter_zp["wh_id"]; 30 31 //获取当前类中的所有公共的方法 32 Type t = this.GetType(); 33 MethodInfo[] mothods = t.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); 34 foreach (MethodInfo item in mothods) 35 { 36 if (item.IsPublic && !item.IsConstructor && item.GetParameters().Length == 0 && item.Name != "GetParameters") 37 { 38 try 39 { 40 item.Invoke(this, null); 41 } 42 catch (Exception ex) 43 { 44 exs.Add(string.Format("方法名:{0} ->参数parameter1:{1} ->参数areaCode:{2} ->异常信息:{3}", item.Name.ToString(), parameter1.ToString(), areaCode.ToString(), ex.Message)); 45 } 46 } 47 } 48 } 49 Assert.True(exs.Count == 0, string.Join("\r\n", exs.ToArray())); 50 } 51 else 52 { 53 Assert.Fail("d_meter_zp表获取的数据为空"); 54 } 55 #endregion 56 57 } 58 59 #region MethodShare 公共方法,ExecuteSql()获取数据库数据;TestType()比较从数据库中获取的数据是否是指定类型,指定类型是数组,可增可减 60 61 /// <summary> 62 /// 连接数据库读取数据 63 /// </summary> 64 /// <param name="conn">oracle数据库连接</param> 65 /// <param name="sql">sql语句</param> 66 /// <param name="para">参数</param> 67 /// <returns>数据</returns> 68 private System.Collections.IEnumerable ExecuteSql(OracleConnection conn, string sql, params OracleParameter[] para) 69 { 70 OracleCommand cmd = conn.CreateCommand(); 71 cmd.CommandText = sql; 72 if (para != null) 73 { 74 foreach (var item in para) 75 { 76 cmd.Parameters.Add(item); 77 } 78 } 79 conn.Open(); 80 OracleDataReader odr = cmd.ExecuteReader(); 81 while (odr.Read()) 82 { 83 yield return odr.GetValue(0); 84 } 85 } 86 87 /// <summary> 88 /// 结果集中得到每列的类型 89 /// </summary> 90 /// <param name="types">需要比较的已知类型</param> 91 /// <param name="conn">连接</param> 92 /// <param name="sql">sql语句</param> 93 /// <param name="para">参数</param> 94 /// <returns>获取的类型与要比较的已知是否一致,bool</returns> 95 private bool TestType(Type[] types, OracleConnection conn, string sql, params OracleParameter[] para) 96 { 97 return types.SequenceEqual(ExecuteSql(conn, sql, para).OfType<object>().Select(o => o.GetType())); 98 99 //int i = 0; 100 //foreach (var o in ExecuteSql(conn, sql, para)) 101 //{ 102 // if (o.GetType() != types[i]) 103 // return false; 104 // i++; 105 //} 106 //return true; 107 } 108 109 #endregion 110 111 #region StockInfoBack 112 113 /// <summary> 预期类型 114 /// 测试StockInfoBack 115 /// 表d_meter_zp 116 /// 表d_stock_pos 117 /// 表d_it 118 /// 表d_stock_pos 119 /// 表d_lc_equip 120 /// 表d_stock_pos 121 /// </summary> 122 // [Test] 123 public void TestStockInfoBack_type() 124 { 125 using (OracleConnection conn = new OracleConnection(conStr)) 126 { 127 OracleParameter[] para = { new OracleParameter("@areaCode", areaCode) };//参数 128 Assert.True(TestType(new Type[] { typeof(string) }, conn, SQLstatements.sqlStockInfoBack, para), "StockInfoBack:类型不一致,areaCode:" + areaCode.ToString());//断言是否正确--调用比较类型是否一致的方法, 129 } 130 } 131 132 /// <summary>读出的数据是否为空 133 /// 测试读取的数据库是否为空 134 /// </summary> 135 /// <param name="areaCode"></param> 136 // [Test] 137 public void TestStockInfoBack_isnull() 138 { 139 using (OracleConnection conn = new OracleConnection(conStr)) 140 { 141 OracleParameter[] para = { new OracleParameter("@areaCode", areaCode) };//参数 142 var list = ExecuteSql(conn, SQLstatements.sqlStockInfoBack, para).Cast<object>().ToArray();//调用读取数据库数据的方法 143 Assert.IsNotEmpty(list, "数据为空.参数areaCode:" + areaCode.ToString());//断言数组、列表或其他集合不为空 144 } 145 } 146 147 #endregion
1 /// <summary> 2 /// 利用特性给予参数测试,可一次性赋予多个参数执行 3 /// </summary> 4 class SqlTest_Property_Oracle 5 { 6 //1.语句覆盖:语句覆盖就是设计若干个测试用例,运行被测试程序,使得每一条可执行语句至少执行一次。 7 //正常输入,边界输入,非正常输入 8 9 private static readonly string conStr = ConfigurationManager.ConnectionStrings["connection"].ConnectionString;//连接字符串 10 11 #region MethodShare 公共方法,ExecuteSql()获取数据库数据;TestType()比较从数据库中获取的数据是否是指定类型,指定类型是数组,可增可减 12 13 /// <summary> 14 /// 连接数据库读取数据 15 /// </summary> 16 /// <param name="conn">oracle数据库连接</param> 17 /// <param name="sql">sql语句</param> 18 /// <param name="para">参数</param> 19 /// <returns>数据</returns> 20 public System.Collections.IEnumerable ExecuteSql(OracleConnection conn, string sql, params OracleParameter[] para) 21 { 22 OracleCommand cmd = conn.CreateCommand(); 23 cmd.CommandText = sql; 24 if (para != null) 25 { 26 foreach (var item in para) 27 { 28 cmd.Parameters.Add(item); 29 } 30 } 31 conn.Open(); 32 OracleDataReader odr = cmd.ExecuteReader(); 33 while (odr.Read()) 34 { 35 yield return odr.GetValue(0); 36 } 37 } 38 39 /// <summary> 40 /// 结果集中得到每列的类型 41 /// </summary> 42 /// <param name="types">需要比较的已知类型</param> 43 /// <param name="conn">连接</param> 44 /// <param name="sql">sql语句</param> 45 /// <param name="para">参数</param> 46 /// <returns>获取的类型与要比较的已知是否一致,bool</returns> 47 public bool TestType(Type[] types, OracleConnection conn, string sql, params OracleParameter[] para) 48 { 49 return types.SequenceEqual(ExecuteSql(conn, sql, para).OfType<object>().Select(o => o.GetType())); 50 51 //int i = 0; 52 //foreach (var o in ExecuteSql(conn, sql, para)) 53 //{ 54 // if (o.GetType() != types[i]) 55 // return false; 56 // i++; 57 //} 58 //return true; 59 } 60 61 #endregion 62 63 #region StockInfoBack 64 65 /// <summary> 预期类型 66 /// </summary> 67 [Category("StockInfoBack")] 68 [TestCase("444")]//正常值 69 [TestCase(" 444 ")]//边界输入 70 [TestCase("rfg-")]//非正常输入 71 [Test] 72 public void TestStockInfoBack_type(string areaCode) 73 { 74 using (OracleConnection conn = new OracleConnection(conStr)) 75 { 76 OracleParameter[] para = { new OracleParameter("@areaCode", areaCode) };//参数 77 Assert.True(TestType(new Type[] { typeof(string) }, conn, SQLstatements.sqlStockInfoBack, para), "StockInfoBack:类型不一致,areaCode:" + areaCode.ToString());//断言是否正确--调用比较类型是否一致的方法, 78 } 79 } 80 81 /// <summary>读出的数据是否为空 82 /// 测试读取的数据库是否为空 83 /// </summary> 84 /// <param name="areaCode"></param> 85 [Category("StockInfoBack")] 86 [Test] 87 public void TestStockInfoBack_isnull(string areaCode) 88 { 89 using (OracleConnection conn = new OracleConnection(conStr)) 90 { 91 OracleParameter[] para = { new OracleParameter("@areaCode", areaCode) };//参数 92 var list = ExecuteSql(conn, SQLstatements.sqlStockInfoBack, para).Cast<object>().ToArray();//调用读取数据库数据的方法 93 Assert.IsNotEmpty(list, "数据为空.参数areaCode:" + areaCode.ToString());//断言数组、列表或其他集合不为空 94 } 95 } 96 97 #endregion
-----------------------------------------------------分割线------------------------------------------------------------
个人笔记——给自己提个醒