在软件的开发过程中,我们离不开测试,在这里我首先送给大家两句关于测试的话keep the bar green to keep the code clear 保持条是绿色则代码是干净的
单元测试并不是为了证明你是对的,而是为了证明你没有错,下面我就简单的介绍一下我总结的使用NUnit的一些方法。
- 如何在Visual Studio.NET 2008中使用NUnit
要在Visual Studio.NET 2008的项目中使用NUnit,首先必须往项目中添加对Nunit框架的引用。方法是在“解决方案资源管理器”窗口中“引用”选项,单击右键,选择“添加引用”,选择“.NET”下面的“nunit.framework.dll”,单击“确定”按钮,回到“解决方案资源管理器”页面,可以看到Nunit已经被添加到项目的引用中。如图所示:
- 小知识点说明
(1).在使用之前先加入命名空间空间using NUnit.Framework;
(2).代码通过“[TestFixture]”来标示出测试类,通过“[Test]”标示出测试方法,这样在测试运行时,NUnit就可以知道这些类和方法是需要测试的,则加载运行单元测试。通过Assert类中的AreEqual方法来判断测试是否通过。如下:
//用TestFixture标示出测试列
[TestFixture]
public class NunitTestClass
{
//用Test标示出测试方法
[Test]
public void TestAddTestClass()
{
Form1 form = new Form1();
int a = 1;
int b = 2;
int expcted = 3;
int actual = form.Add(1, 2);
Assert.AreEqual(expcted, actual);
}
}
(3).测试结果通过的类或方法则以绿色标注,不通过的类或方法以红色标注。黄色表示某些测试被忽略。
- Nunit简单属性总结
(1).[TestFixture] 表示这是一个测试类
(2).[Test] 表示这是一个测试方法
(3). [SetUp] 只要一个函数被标记为[SetUp]属性的话,那么它就会在每一个测试的这些函数或者这些Case进行之前都要去运行一次。它用来在测试之前进行一个初始化的作用。
(4). [TearDown]结束建立,资源回收,每个方法都执行一次。
(5).[TestFixtureSetUp] 表示整个类的初始化,在函数最先执行的时候运行一次。
(6).[TestFixtureTearDown] 表示销毁整个类的初始化,在函数最后呢执行的时候只运行一次。
(7).[Test,Explicit] 显示运行,在Nunit测试器中不选中则不运行,选中的话则会运行
(8).[Test] [Ignore(“this case is ignored”)] 忽略当前这个Case,不让其运行,在Nunit测试其中显示的是黄色。Ignored后面的字符串是为了在Nunit测试其中提示这个信息。
(9).[Test] [Category(GroupName)] 把下面的case归纳在整个组里面,在NUnit里面选中组的话只显示组里面包含的函数。
下面是一个简单的例子:整型冒泡排序的实现及测试
/*在Calculator中写入如下的方法
*整型冒泡排序的实现及测试
*/
public int[] BubbleSort(int[] array)
{
if (null == array)
{
Console.Error.WriteLine("Parameter should't be null");
return new int[] { };
}
for (int i = 0; i < array.Length - 1;++i)
{
bool swap = false;
for (int j = 0; j < array.Length - i - 1; ++j)
{
if (array[j] > array[j + 1])
{
int temp = array[j]; //简单的一个交换
array[j] = array[j + 1];
array[j + 1] = temp;
swap = true;
}
}
if (!swap)
{
return array;
}
}
return array;
}
在测试类CalculatorTest中输入如下的信息:
[Test]
[Category("GroupBubbleSort")]
public void TestBubbleSort()
{
int[] array = { 1,4,4,4,4, 8, 4, 6, 5, 9 };
int[] result = cal.BubbleSort(array);
int[] Expected = { 1, 4,4,4,4,4, 5, 6, 8, 9 };
Assert.AreEqual(Expected, result);
}
[Test]
[Category("GroupBubbleSort")]
public void TestBubbleSort1()
{
int[] array = null;
int[] result = cal.BubbleSort(array);
int[] excepted = { };
Assert.AreEqual(excepted, result);
}
[Test]
[Category("GroupBubbleSort")]
public void TestBubbleSort2()
{
int[] array = { };
int[] result = cal.BubbleSort(array);
int[] excepted = { };
Assert.AreEqual(excepted, result);
}
- 堆栈实例测试知识点
[Test,ExpectedException] 表示期望这个函数抛出一个异常。
新建MyStack类,在类里面模拟实现一些堆栈的知识点代码如下:
namespace NunitTest
{
//模拟测试堆栈,堆栈是数据结构里面的一种类型,后进先出,与之相反的是队列,先进先出
public class MyStack
{
private int nextIndex; //放置的是下一个下标在数组中的元素
private string[] elements; //存放字符串数组
public MyStack() //构造函数
{
elements = new string[100]; //假设数组只能存放100个元素
nextIndex = 0; //下一个元素的索引
}
//定义堆栈的操作
public void push(string element)
{
if (100 == this.nextIndex)
{
throw new Exception("数组越界异常");
}
elements[nextIndex++] = element; //往堆栈里面压的下一个元素
}
public string Pop() //取出数组中的元素
{
if (0 == this.nextIndex)
{
throw new Exception("数组越界异常");
}
return elements[--nextIndex];
}
public void Delete(int n)
{
if (this.nextIndex - n < 0)
{
throw new Exception("数组越界异常");
}
nextIndex -= n; //
}
public string Top()
{
if (0 == this.nextIndex)
{
throw new Exception("数组越界异常");
}
return elements[nextIndex - 1];
}
public int Size()
{
return this.nextIndex;
}
}
}
测试上面的方法是否正确在MystackTest类中,代码如下所示:
namespace NunitTest
{
[TestFixture]
public class MyStackTest
{
private MyStack mystack;
[SetUp]
public void Init()
{
mystack = new MyStack();
}
[Test]
public void TestPush()
{
mystack.push("Hello World");
string result = mystack.Pop();
Assert.AreEqual("Hello World", result);
}
[Test]
public void TestPush2()
{
for (int i = 0; i < 100; ++i)
{
mystack.push(i + "");
}
for (int i = 0; i < 100; ++i)
{
string result = mystack.Pop();
Assert.AreEqual((99 - i) + "", result);
}
}
[Test,ExpectedException]
public void TestPush3()
{
for (int i = 0; i < 101; ++i)
{
mystack.push(i + "");
}
for (int i = 0; i < 100; ++i)
{
string result = mystack.Pop();
Assert.AreEqual((100 - i) + "", result);
}
}
[Test,ExpectedException]
public void TestPop()
{
mystack.Pop();
}
[Test]
public void TestPop2()
{
mystack.push("Hello");
mystack.push("World");
mystack.Pop();
string result = mystack.Pop();
Assert.AreEqual("Hello", result);
}
[Test]
public void TestTop()
{
mystack.push("Hello World");
string result = mystack.Top();
Assert.AreEqual("Hello World", result);
}
[Test,ExpectedException]
public void TestTop2()
{
mystack.Top();
}
[Test]
public void TestDelete()
{
for (int i = 0; i < 10; i++)
{
mystack.push(i + "");
}
mystack.Delete(10);
Assert.AreEqual(0, mystack.Size());
}
[Test,ExpectedException]
public void TestDelete2()
{
for (int i = 0; i < 10; i++)
{
mystack.push(i + "");
}
mystack.Delete(11);
}
}
}
- 对数据库增删改查的一些测试
(1).判断数据库的链接,新建connection类代码如下:
public class connection
{
public static SqlConnection GetConnection() //连接数据库函数
{
string connString = "server=HYL-PC;database=Test;uid=sa;pwd=saa";
SqlConnection connection = new SqlConnection(connString);
try
{
connection.Open();
}
catch
{
return null;
}
return connection;
}
}
在ConnectionTest测试类中输入如下代码,测试连接是否成功
[TestFixture]
public class ConnectionTest
{
[Test]
public void TestGetConnection()
{
SqlConnection conn = connection.GetConnection();
Assert.IsNotNull(conn); //判断其不为空
}
}
- 对数据库增删改查的测试代码如下:新建DBperson类实现数据库增删改查的功能
public void Insert(Person person)
{
string sqlStr = "insert into person(username,password,age)values(@username,@password,@age)";
SqlConnection conn = connection.GetConnection();
SqlCommand command = new SqlCommand(sqlStr, conn);
command.Parameters.Add(new SqlParameter("@username", SqlDbType.VarChar));
command.Parameters.Add(new SqlParameter("@password",SqlDbType.VarChar));
command.Parameters.Add(new SqlParameter("@age", SqlDbType.Int));
command.Parameters["@username"].Value = person.Username;
command.Parameters["@password"].Value = person.Password;
command.Parameters["@age"].Value = person.Age;
try
{
command.ExecuteNonQuery(); //返回受命令影响的行数
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
}
public void Update(Person person)
{
string sqlStr = "update person set username=@username,password=@password,age=@age where id=@id";
SqlConnection conn = connection.GetConnection();
SqlCommand command = new SqlCommand(sqlStr, conn);
command.Parameters.Add(new SqlParameter("@username", SqlDbType.VarChar));
command.Parameters.Add(new SqlParameter("@password", SqlDbType.VarChar));
command.Parameters.Add(new SqlParameter("@age", SqlDbType.Int));
command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int));
command.Parameters["@username"].Value = person.Username;
command.Parameters["@password"].Value = person.Password;
command.Parameters["@age"].Value = person.Age;
command.Parameters["@id"].Value = person.Id;
try
{
command.ExecuteNonQuery();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
}
public Person GetByID(int id)
{
string sqlStr = "select * from person where id=@id";
SqlConnection conn = connection.GetConnection();
SqlCommand command = new SqlCommand(sqlStr, conn);
command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int));
command.Parameters["@id"].Value = id;
SqlDataReader reader = command.ExecuteReader(); //读取到信息
Person person = null;
if (reader.Read())
{
person = new Person();
person.Id = id;
person.Username = reader["username"].ToString();
person.Password = reader["password"].ToString();
person.Age = Convert.ToInt32(reader["age"]);
}
reader.Close();
conn.Close();
return person;
}
public void RemoveID(int id)
{
string sqlStr = "delete from person where id=@id";
SqlConnection conn = connection.GetConnection();
SqlCommand command = new SqlCommand(sqlStr, conn);
command.Parameters.Add(new SqlParameter("@id", SqlDbType.Int));
command.Parameters["@id"].Value = id;
try
{
command.ExecuteNonQuery();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
}
在新建一个测试类:DBPerson类的测试代码如下:
namespace NunitTest
{
[TestFixture]
public class DBPersonTest
{
private DBPerson dbperson;
[TestFixtureSetUp]
public void Init()
{
dbperson = new DBPerson();
}
[Test]
public void TestInsert()
{
Person person = new Person();
person.Username = "韩迎龙";
person.Password = "citsoft";
person.Age = 21;
dbperson.Insert(person);
int maxid = this.GetMaxId();
person.Id = maxid;
Person person2 = dbperson.GetByID(maxid);
this.Company(person, person2);
//做完测试后记得删除数据库中的数据
dbperson.RemoveID(maxid);
}
[Test]
public void TestUpdate()
{
Person person = new Person();
person.Username = "韩鑫";
person.Password = "hanyinglong";
person.Age = 20;
dbperson.Insert(person);
int maxid = this.GetMaxId();
Person person2 = dbperson.GetByID(maxid);
person2.Username = "韩迎龙";
person2.Password = "citsoft";
person2.Age = 20;
dbperson.Update(person2);
Person person3 = dbperson.GetByID(maxid);
this.Company(person2, person3);
dbperson.RemoveID(maxid); //清空数据库
}
[Test]
public void TestGetByID()
{
Person person = new Person();
person.Username = "韩迎龙";
person.Password = "citsoft";
person.Age = 21;
dbperson.Insert(person);
int maxid = this.GetMaxId();
person.Id = maxid;
Person person2 = dbperson.GetByID(maxid);
this.Company(person, person2);
dbperson.RemoveID(maxid);
}
[Test]
public void TestRemoveByID()
{
Person person = new Person();
person.Username = "韩迎龙";
person.Password = "citsoft";
person.Age = 21;
dbperson.Insert(person);
int maxid = this.GetMaxId();
dbperson.RemoveID(maxid);
Person person2 = dbperson.GetByID(maxid);
Assert.IsNull(person2);
}
private int GetMaxId()
{
string sql = "select max(id) as maxID from person";
SqlConnection conn = connection.GetConnection();
SqlCommand command = new SqlCommand(sql, conn);
SqlDataReader reader = command.ExecuteReader();
int maxID = 0;
if (reader.Read())
{
maxID = Convert.ToInt32(reader["maxID"]);
//Console.WriteLine(reader["maxID"]);
}
reader.Close();
conn.Close();
return maxID;
}
private void Company(Person person1, Person person2)
{
Assert.AreEqual(person1.Id, person2.Id);
Assert.AreEqual(person1.Username, person2.Username);
Assert.AreEqual(person1.Password, person2.Password);
Assert.AreEqual(person1.Age, person2.Age);
}
}
}