NUnit单元测试整理高级篇之测试数据库操作以及VS插件TestDriven的使用
本次将着重讲解使用NUnit对数据库操作的测试,对于数据库来说,无非就是查、增、删和改,在这里我针对这四种操作分别讲述一下NUnit的用法,首先我们建立一个数据库,如下:
首先定义如下实体
using System;
namespace NUnitTest
{
public class Person
{
private int id;
private string name;
private string sex;
private string job;
public int Id
{
get { return id; }
set { id = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Sex
{
get { return sex; }
set { sex = value; }
}
public string Job
{
get { return job; }
set { job = value; }
}
}
}
下面的类即为要测试的类,依次为添加、修改、查询和删除
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
namespace NUnitTest
{
public class DbOperator
{
public static void Insert(Person person)
{
SqlConnection connection = DBConnection.CreateCon();
try
{
SqlCommand command = new SqlCommand("insert into Person(Name,Sex,Job) values(@Name,@Sex,@Job)", connection);
SqlParameter[] parameters = {
new SqlParameter("@Name",SqlDbType.NVarChar,16),
new SqlParameter("@Sex",SqlDbType.NVarChar,6),
new SqlParameter("@Job",SqlDbType.NVarChar,50)
};
parameters[0].Value = person.Name;
parameters[1].Value = person.Sex;
parameters[2].Value = person.Job;
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
connection.Open();
command.ExecuteNonQuery();
command.Parameters.Clear();
}
catch (Exception ex)
{
throw new Exception(ex.Message.ToString());
}
finally
{
connection.Close();
}
}
public static void Update(Person person)
{
SqlConnection connection = DBConnection.CreateCon();
try
{
SqlCommand command = new SqlCommand("update Person set Name=@Name,Sex=@Sex,Job=@Job where id=@id", connection);
SqlParameter[] parameters = {
new SqlParameter("@id",SqlDbType.Int),
new SqlParameter("@Name",SqlDbType.NVarChar,16),
new SqlParameter("@Sex",SqlDbType.NVarChar,6),
new SqlParameter("@Job",SqlDbType.NVarChar,50)
};
parameters[0].Value = person.Id;
parameters[1].Value = person.Name;
parameters[2].Value = person.Sex;
parameters[3].Value = person.Job;
foreach (SqlParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
connection.Open();
command.ExecuteNonQuery();
command.Parameters.Clear();
}
catch (Exception ex)
{
Console.Write(ex.Message.ToString());
}
finally
{
connection.Close();
}
}
public static Person GetById(int id)
{
SqlConnection connection = DBConnection.CreateCon();
Person person = new Person();
try
{
SqlCommand command = new SqlCommand("select * from Person where id=@id", connection);
SqlParameter parameter = new SqlParameter("@id", SqlDbType.Int);
parameter.Value = id;
command.Parameters.Add(parameter);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
person.Id = Int32.Parse(reader[0].ToString());
person.Name = reader[1].ToString();
person.Sex = reader[2].ToString();
person.Job = reader[3].ToString();
}
command.Parameters.Clear();
reader.Close();
connection.Close();
return person;
}
catch (Exception)
{
return null;
}
}
public static void RemoveAtId(int id)
{
SqlConnection connection = DBConnection.CreateCon();
try
{
SqlCommand command = new SqlCommand("delete from Person where id=@id", connection);
SqlParameter parameter = new SqlParameter("@id", SqlDbType.Int);
parameter.Value = id;
command.Parameters.Add(parameter);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
catch (Exception ex)
{
Console.Write(ex.Message.ToString());
}
}
}
}
下面就是针对上述方法的测试
using System;
using System.Collections.Generic;
using NUnit.Framework;
using System.Data;
using System.Data.SqlClient;
namespace NUnitTest
{
[TestFixture]
public class DbOperatorTest
{
private SqlConnection connection;
[TestFixtureSetUp]
public void Init()
{
connection = DBConnection.CreateCon();
}
[TestFixtureTearDown]
public void Destroy()
{
connection = null;
}
[Test]
public void TestInsert()
{
Person person1 = new Person();
person1.Name = "张三";
person1.Sex = "男";
person1.Job = "软件工程师";
DbOperator.Insert(person1);
int maxId = GetMaxId();
person1.Id = maxId;
Person person2 = DbOperator.GetById(maxId);
this.Compare(person1, person2);
//记得测试完成之后删除数据库中的数据
DbOperator.RemoveAtId(maxId);
}
[Test]
public void TestUpdate()
{
Person person1 = new Person();
person1.Name = "张三";
person1.Sex = "男";
person1.Job = "软件工程师";
//测试用例不能依赖于外部数据库,这是测试最基本的原则,所以在这里我们必须手动增加一条记录测试
DbOperator.Insert(person1);
int maxId = this.GetMaxId();
Person person2 = DbOperator.GetById(maxId);
person2.Name = "李四";
person2.Sex = "女";
person2.Job = "行政总监";
DbOperator.Update(person2);
Person person3 = DbOperator.GetById(maxId);
this.Compare(person2, person3);
//记得测试完成之后删除数据库中的数据
DbOperator.RemoveAtId(maxId);
}
[Test]
public void TestGetById()
{
Person person1 = new Person();
person1.Name = "张三";
person1.Sex = "男";
person1.Job = "软件工程师";
DbOperator.Insert(person1);
int maxId = this.GetMaxId();
person1.Id = maxId;
Person person2 = DbOperator.GetById(maxId);
this.Compare(person1, person2);
DbOperator.RemoveAtId(maxId);
}
[Test]
public void TestRemoveAtId()
{
Person person1 = new Person();
person1.Name = "张三";
person1.Sex = "男";
person1.Job = "软件工程师";
DbOperator.Insert(person1);
int maxId = this.GetMaxId();
DbOperator.RemoveAtId(maxId);
Person person2 = DbOperator.GetById(maxId);
this.Compare(new Person(), person2);
}
void Compare(Person person1, Person person2)
{
Assert.AreEqual(person1.Id, person2.Id);
Assert.AreEqual(person1.Name, person2.Name);
Assert.AreEqual(person1.Sex, person2.Sex);
Assert.AreEqual(person1.Job, person2.Job);
}
public int GetMaxId()
{
try
{
SqlCommand command = new SqlCommand("select max(id) from Person", connection);
connection.Open();
int result = Convert.ToInt32(command.ExecuteScalar());
connection.Close();
return result;
}
catch (Exception)
{
return 0;
}
}
}
}
针对上面比较庞大的一个TestCase,本身难免会出现问题。如果自身出了问题,那么用NUnit相对就不是那么友好,因为它不能进行断点调试,这样势必在浪费我们宝贵的开发时间,在这里我推荐一个名叫TestDriven的基于NUnit的插件,本身可以同VS无缝集成,同时可提供对TestCase自身的很强大的调试功能,并且支持断点调试,下载地址我先给出来:http://www.testdriven.net,在这里我用的是个人版,因为其他的要给钱,个人目前用到的个人版就已经足够了。。。
下面依次讲述一下以下内容:
1.执行某个测试类的单个TestCase
在某个TestCase的内部或名称上单击鼠标右键>>Run Test(s),即可执行这个TestCase
2.执行某个测试类的所有TestCase
在某个类的所有TestCase的外部或在解决方案资源管理器中选中该类后,单击鼠标右键>>Run Test(s)
3.执行整个命名空间下的TestCase
在解决方案资源管理器中选中项目名称,即可执行该项目下所有的TestCase,方法同上。
4.用断点调试来调试某个TestCase
在某个TestCase内部设置了断点后,在该TestCase的内部或名称上单击鼠标右键>>Test With>>Debugger即可单步调试该TestCase
5.显示整个项目的测试覆盖率,一般达到80%以上就很好了。
在项目名称上单击鼠标右键>>Test With>>Coverage,即可显示测试覆盖率。
------本系列终结