簡(jiǎn)介
編寫(xiě)單元測(cè)試是一種驗(yàn)證行為,更是一種設(shè)計(jì)行為。同樣,它更是一種編寫(xiě)文檔的行為。編寫(xiě)單元測(cè)試避免了相當(dāng)數(shù)量的反饋循環(huán),尤其是功能驗(yàn)證方面的反饋循環(huán)。
雖然由程序開(kāi)發(fā)人員自己寫(xiě)Unit Tests(單元測(cè)試)來(lái)測(cè)試自己寫(xiě)的程序代碼已經(jīng)行之有年,但是大部分的Unit Tests都是寫(xiě)在主要的程序代碼已經(jīng)設(shè)計(jì)好、寫(xiě)好之后。大部分的程序開(kāi)發(fā)人員都有相同的的經(jīng)驗(yàn),在主要程序代碼寫(xiě)好之后再來(lái)加入U(xiǎn)nit Test是一項(xiàng)困難的工作,而且在時(shí)間的壓力之下Unit Test通常是第一個(gè)被跳過(guò)的步驟.本篇文章介紹的是一個(gè).NET平臺(tái)的單元測(cè)試工具NUnit。
什么是Unit Tests(單元測(cè)試)?
在程序設(shè)計(jì)過(guò)程中會(huì)有許多種測(cè)試,單元只是其中的一種,單元測(cè)試并不能保證程序是完美無(wú)缺的,但是在所有的測(cè)試中,單元測(cè)試是第一個(gè)環(huán)節(jié),也是重要的一個(gè)環(huán)節(jié)。單元測(cè)試是一種由程序員自行測(cè)試的工作。簡(jiǎn)單點(diǎn)說(shuō),單元測(cè)試是測(cè)試代碼撰寫(xiě)者依據(jù)其所設(shè)想的方式執(zhí)行是否產(chǎn)生了預(yù)期的結(jié)果。關(guān)于單元測(cè)試的重要性已經(jīng)有許多文章做了很多深入的分析,這里不再贅述。NUnit是一個(gè)為Net準(zhǔn)備的自動(dòng)化單元測(cè)試框架,它的作用是幫助你方便的完成單元測(cè)試工作,同鼎鼎有名的JUnit一樣,都是xUnit家族的成員。它的下載地址是:http://www.nunit.org/。
NUnit Framework(NUnit 單元測(cè)試框架)簡(jiǎn)介
本文所討論的NUnit 2.1是一個(gè)與它的先祖?zhèn)?其它的Framework)非常不一樣的版本。其它的xUnit家族版本通常都有一個(gè)base class(基礎(chǔ)類(lèi)),你要寫(xiě)的test classes(測(cè)試用例)都得inherit(繼承)自這個(gè)base class。除此之外,別無(wú)他法能夠讓你寫(xiě)Unit Tests。不幸的是,這對(duì)很多的程序語(yǔ)言來(lái)說(shuō)造成很大的限制。比如說(shuō),Java及C#只能允許single inheritance(單一繼承)。也是說(shuō),如果你想要refactor(重構(gòu))你的Unit Tests程序代碼的話(huà),你會(huì)遇到一些的限制;除非你引進(jìn)一些復(fù)雜的inheritance hierarchies(類(lèi)別繼承層級(jí))。有了.NET之后一切又不同了,.NET引進(jìn)了一個(gè)新的程序開(kāi)發(fā)的概念 ─ Attributes(屬性),解決了這個(gè)煩人的問(wèn)題。Attributes讓你可以在你的程序代碼之上再加入metadata(元數(shù)據(jù),描述程序代碼的資料)。一般來(lái)說(shuō)Attributes不會(huì)影響到主要程序代碼的執(zhí)行,其功能是在你所寫(xiě)程序代碼之上添加了額外的信息。Attributes主要使用在 documenting your code(注釋你的程序代碼),但是Attributes也可以用來(lái)提供有關(guān)Assembly的額外信息,其它的程序算沒(méi)有見(jiàn)過(guò)這個(gè)Assembly,也可以使用這些信息。這基本上是NUnit 2.1所作的事。在NUnit 2.1里面,有一個(gè)Test Runner Application(負(fù)責(zé)執(zhí)行Unit Tests的程序),這個(gè)Test Runner會(huì)掃描你已經(jīng)compile(編譯)好的程序代碼,并且從Attribute里面知道哪些classes是test classes,哪些methods是需要執(zhí)行的test methods. 然后,Test Runner使用.NET的Reflection技術(shù)(在.NET Framework中提供了System.Reflection命名空間,這樣使得我們可以方便的獲得.NET組件的信息。當(dāng)你想獲得正在使用的組件的詳細(xì)信息,或者在運(yùn)行期間查詢(xún)一個(gè)組件信息的時(shí)候,這個(gè)功能將變的十分有用)來(lái)執(zhí)行這些test methods。因?yàn)檫@個(gè)原因,你不再需要讓你的test classes繼承自所謂的common base class。你需要作的事,是使用正確的Attribute來(lái)描述你的test classes及test methods。NUnit提供了許多不同的attributes,讓你可以自由的寫(xiě)你想要的unit tests。這些attributes可以用來(lái)定義test fixtures(見(jiàn)下一段解釋)、test methods,以及setup及teardown的methods(預(yù)備及善后工作的methods)。除此之外,還有其它的attributes可以來(lái)設(shè)定預(yù)期發(fā)生的exceptions,或者要求Test Runner跳過(guò)某些test method不執(zhí)行。
TestFixture Attribute簡(jiǎn)介
TestFixture attribute主要是用在class上,其作用是標(biāo)志該class含有需要執(zhí)行的test methods。當(dāng)你在一個(gè)class的定義里加上這個(gè)attribute,Test Runner會(huì)檢查該class,看看這個(gè)class是否含有test methods。底下這段程序代碼示范了如何使用TestFixture Attribute。(本文中所有程序代碼都是用C#寫(xiě)成,但是你應(yīng)該知道,NUnit也是用于其它的.NET程序語(yǔ)言,包括VB.NET。請(qǐng)參見(jiàn)NUnit的相關(guān)文件。
namespace UnitTestingExamples
{
using System;
using NUnit.Framework;
[TestFixture]
public class SomeTests
{
}
}
使用TextFixture Attribute的class需要符合另一項(xiàng)附加的限制,是需要有一個(gè)public的default constructor(或者是沒(méi)有定義任何的constructor,這其實(shí)是相同的意思)。
TestFixtureSetUp 和TestFixtureTearDown簡(jiǎn)介
這兩個(gè)主要用在TestFixture里面,其作用是提供一組函數(shù)執(zhí)行任何測(cè)試運(yùn)行之前(TestFixtureSetUP)和后一個(gè)測(cè)試執(zhí)行后(TestFixtureTearDown)。每一個(gè)TestFixture只能有一個(gè)TestFixtureSetUp方法和 TestFixtureTearDown方法。如果一個(gè)以上的TestFixtureSetUp和TestFixtureTearDown方法,可以通過(guò)編譯但是不會(huì)執(zhí)行。注意一個(gè)TestFixture可以擁有一個(gè)TestFixtureSetUp和一個(gè)SetUp,也可以擁有一個(gè) TestFixtureTearDown和一個(gè)TearDown方法。
TestFixtureSetUp 和 TestFixtureTearDown 被用在不方便使用SetUp和TearDown方法。
一般情況使用 SetUp 和TearDown attributes。