测试驱动开发例子学习-Using TDD with ADO.NET
2007-10-25 21:25
756 查看
来源:博客园使用智能客户端http://www.cnblogs.com/jasonw/archive/2004/10/10/50659.html
1.连接字符串的测试驱动范例:
[align=left]DataBase-SQLServer2000:
1.ConnectingtotheDatabase
2.XML应用程序的配置文件:
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
<appSettings>
<addkey="Catalog.Connection"
value="server=(local);database=catalog;Trusted_Connection=true"/>
</appSettings>
</configuration>
[/align]
[align=left]usingSystem;[/align]
[align=left]usingSystem.Data;[/align]
[align=left]usingSystem.Data.SqlClient;[/align]
[align=left]usingNUnit.Framework;[/align]
[align=left][/align]
[align=left][TestFixture][/align]
[align=left]publicclassSqlConnectionFixture[/align]
[align=left]{[/align]
[align=left][Test][/align]
[align=left]publicvoidConnectionIsOpen()[/align]
[align=left]{
//使用配置文件定义连接字符串
//stringconnectionString=[/align]
[align=left]//ConfigurationSettings.AppSettings.Get("Catalog.Connection");[/align]
[align=left]//Assert.IsNotNull(connectionString);[/align]
[align=left][/align]
[align=left]SqlConnectionconnection=[/align]
[align=left]newSqlConnection([/align]
[align=left]@"server=(local);database=catalog;Trusted_Connection=true");[/align]
[align=left]connection.Open();[/align]
[align=left]Assert.AreEqual(ConnectionState.Open,connection.State);[/align]
[align=left]connection.Close();[/align]
[align=left]}[/align]
[align=left]}
[/align]
2.连接字符串的测试驱动优化范例:
[align=left]
以上代码可以替换为:[/align]
[align=left][TestFixture][/align]
[align=left]publicclassSqlConnectionFixture[/align]
[align=left]{[/align]
[align=left]privatestringconnectionString;[/align]
[align=left][/align]
[align=left][SetUp][/align]
[align=left]publicvoidRetrieveConnectionString()[/align]
[align=left]{[/align]
[align=left]connectionString=[/align]
[align=left]ConfigurationSettings.AppSettings.Get("Catalog.Connection");[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][Test][/align]
[align=left]publicvoidCanRetrieveConnectionString()[/align]
[align=left]{[/align]
[align=left]Assert.IsNotNull(connectionString);[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][Test][/align]
[align=left]publicvoidConnectionIsOpen()[/align]
[align=left]{[/align]
[align=left]SqlConnectionconnection=[/align]
[align=left]newSqlConnection(connectionString);[/align]
[align=left]connection.Open();[/align]
[align=left]Assert.AreEqual(ConnectionState.Open,connection.State);[/align]
[align=left]connection.Close();[/align]
[align=left]}[/align]
[align=left]}
[/align]
3.ArtistGateway实现数据访问层的一个范例
对数据表artist的通用操作
4.ArtistFixture.cs数据访问层代理类的测试用例
5.删除驱动所形成的实现代码:
[align=left]publicvoidDelete(RecordingDataSetrecordingDataSet,longartistId)[/align]
[align=left]{[/align]
[align=left]RecordingDataSet.ArtistloadedArtist=[/align]
[align=left]FindById(artistId,recordingDataSet);[/align]
[align=left][/align]
[align=left]loadedArtist.Delete();[/align]
[align=left][/align]
[align=left]adapter.Update(recordingDataSet,[/align]
[align=left]recordingDataSet.Artists.TableName);[/align]
}
6.有了完整的测试用例,以及实现的代码,可以进行重构:
//首先优化测试的代码:
7.在重构的基础上加入更新方法:.
//ThefollowingistheimplementationofUpdate:
8.GenreGateway另一个测试驱动的例子(类似于artists)
9.实现部分GenreGateway:
10.获取下一个ID
//实现部分
11.IdGeneratorFixture.cs优化过得实现:
1.连接字符串的测试驱动范例:
[align=left]DataBase-SQLServer2000:
1.ConnectingtotheDatabase
2.XML应用程序的配置文件:
<?xmlversion="1.0"encoding="utf-8"?>
<configuration>
<appSettings>
<addkey="Catalog.Connection"
value="server=(local);database=catalog;Trusted_Connection=true"/>
</appSettings>
</configuration>
[/align]
[align=left]usingSystem;[/align]
[align=left]usingSystem.Data;[/align]
[align=left]usingSystem.Data.SqlClient;[/align]
[align=left]usingNUnit.Framework;[/align]
[align=left][/align]
[align=left][TestFixture][/align]
[align=left]publicclassSqlConnectionFixture[/align]
[align=left]{[/align]
[align=left][Test][/align]
[align=left]publicvoidConnectionIsOpen()[/align]
[align=left]{
//使用配置文件定义连接字符串
//stringconnectionString=[/align]
[align=left]//ConfigurationSettings.AppSettings.Get("Catalog.Connection");[/align]
[align=left]//Assert.IsNotNull(connectionString);[/align]
[align=left][/align]
[align=left]SqlConnectionconnection=[/align]
[align=left]newSqlConnection([/align]
[align=left]@"server=(local);database=catalog;Trusted_Connection=true");[/align]
[align=left]connection.Open();[/align]
[align=left]Assert.AreEqual(ConnectionState.Open,connection.State);[/align]
[align=left]connection.Close();[/align]
[align=left]}[/align]
[align=left]}
[/align]
2.连接字符串的测试驱动优化范例:
[align=left]
以上代码可以替换为:[/align]
[align=left][TestFixture][/align]
[align=left]publicclassSqlConnectionFixture[/align]
[align=left]{[/align]
[align=left]privatestringconnectionString;[/align]
[align=left][/align]
[align=left][SetUp][/align]
[align=left]publicvoidRetrieveConnectionString()[/align]
[align=left]{[/align]
[align=left]connectionString=[/align]
[align=left]ConfigurationSettings.AppSettings.Get("Catalog.Connection");[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][Test][/align]
[align=left]publicvoidCanRetrieveConnectionString()[/align]
[align=left]{[/align]
[align=left]Assert.IsNotNull(connectionString);[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][Test][/align]
[align=left]publicvoidConnectionIsOpen()[/align]
[align=left]{[/align]
[align=left]SqlConnectionconnection=[/align]
[align=left]newSqlConnection(connectionString);[/align]
[align=left]connection.Open();[/align]
[align=left]Assert.AreEqual(ConnectionState.Open,connection.State);[/align]
[align=left]connection.Close();[/align]
[align=left]}[/align]
[align=left]}
[/align]
3.ArtistGateway实现数据访问层的一个范例
对数据表artist的通用操作
usingSystem;
usingSystem.Data;
usingSystem.Data.SqlClient;
namespaceDataAccessLayer
{
publicclassArtistGateway
{
privateSqlDataAdapteradapter;
privateSqlConnectionconnection;
privateSqlCommandcommand;
privateSqlCommandBuilderbuilder;
publicArtistGateway(SqlConnectionconnection)
{
this.connection=connection;
command=newSqlCommand(
"selectid,namefromartistwhereid=@id",
connection);
command.Parameters.Add("@id",SqlDbType.BigInt);
adapter=newSqlDataAdapter(command);
builder=newSqlCommandBuilder(adapter);
}
publiclongInsert(
RecordingDataSetrecordingDataSet,stringartistName)
{
longartistId=
GetNextId(recordingDataSet.Artists.TableName);
RecordingDataSet.ArtistartistRow=
recordingDataSet.Artists.NewArtist();
artistRow.Id=artistId;
artistRow.Name=artistName;
recordingDataSet.Artists.AddArtist(artistRow);
adapter.Update(recordingDataSet,
recordingDataSet.Artists.TableName);
returnartistId;
}
publicRecordingDataSet.Artist
FindById(longartistId,RecordingDataSetrecordingDataSet)
{
command.Parameters["@id"].Value=artistId;
adapter.Fill(recordingDataSet,
recordingDataSet.Artists.TableName);
DataRow[]rows=recordingDataSet.Artists.Select(
String.Format("id={0}",artistId));
if(rows.Length<1)returnnull;
return(RecordingDataSet.Artist)rows[0];
}
publiclongGetNextId(stringtableName)
{
SqlTransactiontransaction=
connection.BeginTransaction(
IsolationLevel.Serializable,"GenerateId");
SqlCommandselectCommand=newSqlCommand(
"selectnextIdfromPKSequencewheretableName=@tableName",
connection,transaction);
selectCommand.Parameters.Add("@tableName",
SqlDbType.VarChar).Value=tableName;
longnextId=(long)selectCommand.ExecuteScalar();
SqlCommandupdateCommand=newSqlCommand(
"updatePKSequencesetnextId=@nextIdwheretableName=@tableName",
connection,transaction);
updateCommand.Parameters.Add("@tableName",
SqlDbType.VarChar).Value=tableName;
updateCommand.Parameters.Add("@nextId",
SqlDbType.BigInt).Value=nextId+1;
updateCommand.ExecuteNonQuery();
transaction.Commit();
returnnextId;
}
4.ArtistFixture.cs数据访问层代理类的测试用例
usingSystem;
usingSystem.Configuration;
usingSystem.Data;
usingSystem.Data.SqlClient;
usingDataAccessLayer;
usingNUnit.Framework;
[TestFixture]
publicclassArtistFixture
{
[Test]
publicvoidRetrieveArtistFromDatabase()
{
stringartistName="Artist";
SqlConnectionconnection=
newSqlConnection(
ConfigurationSettings.AppSettings.Get(
"Catalog.Connection"));
connection.Open();
ArtistGatewaygateway=newArtistGateway(connection);
longartistId=
gateway.Insert(newRecordingDataSet(),artistName);
RecordingDataSetloadedFromDB=newRecordingDataSet();
RecordingDataSet.ArtistloadedArtist=
gateway.FindById(artistId,loadedFromDB);
Assert.AreEqual(artistId,loadedArtist.Id);
Assert.AreEqual(artistName,loadedArtist.Name);
gateway.Delete(loadedFromDB,artistId);//删除功能的驱动
connection.Close();
}
}
5.删除驱动所形成的实现代码:
[align=left]publicvoidDelete(RecordingDataSetrecordingDataSet,longartistId)[/align]
[align=left]{[/align]
[align=left]RecordingDataSet.ArtistloadedArtist=[/align]
[align=left]FindById(artistId,recordingDataSet);[/align]
[align=left][/align]
[align=left]loadedArtist.Delete();[/align]
[align=left][/align]
[align=left]adapter.Update(recordingDataSet,[/align]
[align=left]recordingDataSet.Artists.TableName);[/align]
}
6.有了完整的测试用例,以及实现的代码,可以进行重构:
//首先优化测试的代码:
[TestFixture]
publicclassArtistFixture
{
privatestaticreadonlystringartistName="Artist";
privateSqlConnectionconnection;
privateArtistGatewaygateway;
privateRecordingDataSetrecordingDataSet;
privatelongartistId;
[SetUp]
publicvoidSetUp()
{
connection=newSqlConnection(
ConfigurationSettings.AppSettings.Get(
"Catalog.Connection"));
connection.Open();
recordingDataSet=newRecordingDataSet();
gateway=newArtistGateway(connection);
artistId=gateway.Insert(recordingDataSet,artistName);
}
[TearDown]
publicvoidTearDown()
{
gateway.Delete(recordingDataSet,artistId);
connection.Close();
}
[Test]
publicvoidRetrieveArtistFromDatabase()
{
RecordingDataSetloadedFromDB=newRecordingDataSet();
RecordingDataSet.ArtistloadedArtist=
gateway.FindById(artistId,loadedFromDB);
Assert.AreEqual(artistId,loadedArtist.Id);
Assert.AreEqual(artistName,loadedArtist.Name);
}
[Test]
publicvoidDeleteArtistFromDatabase()
{
RecordingDataSetemptyDataSet=newRecordingDataSet();
longdeletedArtistId=gateway.Insert(emptyDataSet,"DeletedArtist");
gateway.Delete(emptyDataSet,deletedArtistId);
RecordingDataSet.ArtistdeleletedArtist=
gateway.FindById(deletedArtistId,emptyDataSet);
Assert.IsNull(deleletedArtist);
}
}
7.在重构的基础上加入更新方法:.
[Test]
publicvoidUpdateArtistInDatabase()
{
RecordingDataSet.Artistartist=recordingDataSet.Artists[0];
artist.Name="ModifiedName";
gateway.Update(recordingDataSet);
RecordingDataSetupdatedDataSet=newRecordingDataSet();
RecordingDataSet.ArtistupdatedArtist=
gateway.FindById(artistId,updatedDataSet);
Assert.AreEqual("ModifiedName",updatedArtist.Name);
}
//ThefollowingistheimplementationofUpdate:
publicvoidUpdate(RecordingDataSetrecordingDataSet)
{
adapter.Update(recordingDataSet,
recordingDataSet.Artists.TableName);
}
8.GenreGateway另一个测试驱动的例子(类似于artists)
[TestFixture]
publicclassGenreFixture
{
privatestaticreadonlystringgenreName="Rock";
privateSqlConnectionconnection;
privateGenreGatewaygateway;
privateRecordingDataSetrecordingDataSet;
privatelonggenreId;
[SetUp]
publicvoidSetUp()
{
connection=newSqlConnection(
ConfigurationSettings.AppSettings.Get(
"Catalog.Connection"));
connection.Open();
recordingDataSet=newRecordingDataSet();
gateway=newGenreGateway(connection);
genreId=gateway.Insert(recordingDataSet,genreName);
}
[TearDown]
publicvoidTearDown()
{
gateway.Delete(recordingDataSet,genreId);
connection.Close();
}
[Test]
publicvoidRetrieveGenreFromDatabase()
{
RecordingDataSetloadedFromDB=newRecordingDataSet();
RecordingDataSet.GenreloadedGenre=
gateway.FindById(genreId,loadedFromDB);
Assert.AreEqual(genreId,loadedGenre.Id);
Assert.AreEqual(genreName,loadedGenre.Name);
}
}
9.实现部分GenreGateway:
publicclassGenreGateway
{
privateSqlDataAdapteradapter;
privateSqlConnectionconnection;
privateSqlCommandcommand;
privateSqlCommandBuilderbuilder;
publicGenreGateway(SqlConnectionconnection)
{
this.connection=connection;
command=newSqlCommand(
"selectid,namefromGenrewhereid=@id",
connection);
command.Parameters.Add("@id",SqlDbType.BigInt);
adapter=newSqlDataAdapter(command);
builder=newSqlCommandBuilder(adapter);
}
publiclongInsert(RecordingDataSetrecordingDataSet,
stringgenreName)
{
longgenreId=GetNextId(recordingDataSet.Genres.TableName);
RecordingDataSet.GenregenreRow=
recordingDataSet.Genres.NewGenre();
genreRow.Id=genreId;
genreRow.Name=genreName;
recordingDataSet.Genres.AddGenre(genreRow);
adapter.Update(recordingDataSet,
recordingDataSet.Genres.TableName);
returngenreId;
}
publicRecordingDataSet.Genre
FindById(longgenreId,RecordingDataSetrecordingDataSet)
{
command.Parameters["@id"].Value=genreId;
adapter.Fill(recordingDataSet,
recordingDataSet.Genres.TableName);
DataRow[]rows=recordingDataSet.Genres.Select(
String.Format("id={0}",genreId));
if(rows.Length<1)returnnull;
return(RecordingDataSet.Genre)rows[0];
}
publicvoidDelete(RecordingDataSetrecordingDataSet,
longgenreId)
{
RecordingDataSet.GenreloadedGenre=
FindById(genreId,recordingDataSet);
loadedGenre.Delete();
adapter.Update(recordingDataSet,
recordingDataSet.Genres.TableName);
}
publiclongGetNextId(stringtableName)
{/*sameasinArtistGateway*/}
}
10.获取下一个ID
[TestFixture]
publicclassIdGeneratorFixture
{
privateSqlConnectionconnection;
[SetUp]
publicvoidOpenConnection()
{
connection=newSqlConnection(
ConfigurationSettings.AppSettings.Get(
"Catalog.Connection"));
connection.Open();
}
[Test]
publicvoidGetNextIdIncrement()
{
SqlCommandsqlCommand=newSqlCommand(
"selectnextIdfromPKSequencewheretableName=@tableName",
connection);
sqlCommand.Parameters.Add(
"@tableName",SqlDbType.VarChar).Value="Artist";
longnextId=(long)sqlCommand.ExecuteScalar();
longnextIdFromGenerator=
IdGenerator.GetNextId("Artist",connection);
Assert.AreEqual(nextId,nextIdFromGenerator);
nextId=(long)sqlCommand.ExecuteScalar();
Assert.AreEqual(nextId,nextIdFromGenerator+1);
}
[TearDown]
publicvoidCloseConnection()
{
connection.Close();
}
}
//实现部分
publicclassIdGenerator
{
publicstaticlongGetNextId(stringtableName,
SqlConnectionconnection)
{
SqlTransactiontransaction=connection.BeginTransaction(
IsolationLevel.Serializable,"GenerateId");
SqlCommandselectCommand=newSqlCommand(
"selectnextIdfromPKSequencewheretableName=@tableName",
connection,transaction);
selectCommand.Parameters.Add("@tableName",
SqlDbType.VarChar).Value=tableName;
longnextId=(long)selectCommand.ExecuteScalar();
SqlCommandupdateCommand=newSqlCommand(
"updatePKSequencesetnextId=@nextIdwheretableName=@tableName",
connection,transaction);
updateCommand.Parameters.Add("@tableName",SqlDbType.VarChar).Value=tableName;
updateCommand.Parameters.Add("@nextId",SqlDbType.BigInt).Value=nextId+1;
updateCommand.ExecuteNonQuery();
transaction.Commit();
returnnextId;
}
}
11.IdGeneratorFixture.cs优化过得实现:
usingSystem;
usingSystem.Configuration;
usingSystem.Data;
usingSystem.Data.SqlClient;
usingNUnit.Framework;
usingDataAccessLayer;
[TestFixture]
publicclassIdGeneratorFixture:ConnectionFixture
{
[Test]
publicvoidGetNextIdIncrement()
{
SqlCommandsqlCommand=
newSqlCommand(
"selectnextIdfromPKSequencewheretableName=@tableName",
Connection);
sqlCommand.Parameters.Add("@tableName",SqlDbType.VarChar).Value="Artist";
longnextId=(long)sqlCommand.ExecuteScalar();
longnextIdFromGenerator=IdGenerator.GetNextId("Artist",Connection);
Assert.AreEqual(nextId,nextIdFromGenerator);
nextId=(long)sqlCommand.ExecuteScalar();
Assert.AreEqual(nextId,nextIdFromGenerator+1);
}
}
相关文章推荐
- 在ASP.NET MVC中使用测试驱动开发 Test Driven Development with ASP.Net MVC (Part 1)
- VS2010 学习笔记 WF4 (5) 加入单元测试,实现测试驱动开发(TDD)
- <Test-Driven Development with Python>学习笔记 第一部分 测试驱动开发基础
- TDD(测试驱动开发)学习一:初识TDD
- TDD(测试驱动开发)学习二:创建第一个TDD程序
- TDD(测试驱动开发)学习二:创建第一个TDD程序
- 测试驱动开发(TDD)实战小例子 (转)
- 测试驱动开发(tdd) 学习笔记(1)基本思想原则和术语
- 测试驱动开发(TDD)实战小例子(JAVA版)
- TDD(测试驱动开发)学习一:初识TDD
- 测试驱动开发(tdd) 学习笔记(1)基本思想原则和术语
- 网友关于TDD(测试驱动开发)的评论
- 用NUnit2.1简单实现.net的测试驱动开发(TDD)
- 如何Vue-cli开始使用在Vue.js项目中启动TDD(测试驱动开发)
- 测试驱动开发(Test-Driven Development,简称TDD)--单元测试-->提高代码质量
- python 测试驱动开发的简单例子
- 你的项目TDD了吗? 有关测试驱动开发的一点想法
- 基于Angularjs+jasmine+karma的测试驱动开发(TDD)实例
- 数据库开发及ADO.NET学习笔记(二)
- 用NUnit2.1简单实现.net的测试驱动开发(TDD)---转帖