六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

數(shù)據(jù)庫程序的單元測(cè)試(ZT)

[摘要]數(shù)據(jù)庫程序的單元測(cè)試本文來自互聯(lián)網(wǎng),原作者不詳。翻譯:PMTeamXu NingNing這些筆錄是我關(guān)于已完成的數(shù)據(jù)庫功能測(cè)試的一些心得。其中的例子是用java語言編寫的,但我認(rèn)為這些想法對(duì)于大多數(shù)編程環(huán)境都普遍適用。當(dāng)然,我仍致力于尋找更佳的解決方案�,F(xiàn)實(shí)的問題是這樣的:你有一個(gè)SQL數(shù)據(jù)庫,一...
數(shù)據(jù)庫程序的單元測(cè)試

本文來自互聯(lián)網(wǎng),原作者不詳。

翻譯:PMTeamXu NingNing



這些筆錄是我關(guān)于已完成的數(shù)據(jù)庫功能測(cè)試的一些心得。其中的例子是用java語言編寫的,但我認(rèn)為這些想法對(duì)于大多數(shù)編程環(huán)境都普遍適用。當(dāng)然,我仍致力于尋找更佳的解決方案。

現(xiàn)實(shí)的問題是這樣的:你有一個(gè)SQL數(shù)據(jù)庫,一些存儲(chǔ)過程和一個(gè)介于應(yīng)用程序和數(shù)據(jù)庫之間的中間層。你怎樣在其中插入測(cè)試代碼從而保證在數(shù)據(jù)庫中數(shù)據(jù)存取功能的實(shí)現(xiàn)?



一、為什么會(huì)有這樣的問題?

我猜想有些,可能不完全是大多數(shù)的數(shù)據(jù)庫開發(fā)過程都是這樣的:建立數(shù)據(jù)庫,編寫存取數(shù)據(jù)到數(shù)據(jù)庫的代碼,編譯并運(yùn)行,用一個(gè)查詢語句查驗(yàn)所列的數(shù)據(jù)是否正確顯示。如果能正確顯示那就大功告成了。

然而,這種靠眼睛來檢測(cè)的弊端在于:你不經(jīng)常進(jìn)行這樣的檢驗(yàn),而且這種檢驗(yàn)是不完全的。存在這樣的可能性,當(dāng)你對(duì)系統(tǒng)進(jìn)行了修改,過了幾個(gè)月后,你無意中破壞了系統(tǒng),從而導(dǎo)致數(shù)據(jù)的丟失。作為一個(gè)編程人員,你可能不會(huì)花很多時(shí)間來檢查數(shù)據(jù)本身,這就使錯(cuò)誤的數(shù)據(jù)要經(jīng)過較長(zhǎng)的時(shí)間才能暴露出來。我曾經(jīng)參與一個(gè)建立網(wǎng)站的項(xiàng)目,該項(xiàng)目中在注冊(cè)時(shí)有一個(gè)必填數(shù)據(jù)在大半年中沒有被發(fā)現(xiàn)未實(shí)際輸入進(jìn)數(shù)據(jù)庫。盡管公司市場(chǎng)部曾經(jīng)提出他們需要這一信息,但因?yàn)檫@項(xiàng)數(shù)據(jù)從來沒有人去看它,直接導(dǎo)致了這一問題在很長(zhǎng)時(shí)間內(nèi)沒有被發(fā)現(xiàn)。

自動(dòng)化測(cè)試,由于它能經(jīng)常測(cè)試而且測(cè)試范圍較廣,降低了數(shù)據(jù)丟失的風(fēng)險(xiǎn)。我發(fā)現(xiàn)它能使我更心安理得地休息。當(dāng)然,自動(dòng)化測(cè)試還有其他一些好處,他們本身就是代碼編寫的范例,也可以作為文檔,便于你修改別人編寫的原始程序,從而減少檢測(cè)所需的時(shí)間。





二、什么是我們所談?wù)摰臏y(cè)試?



設(shè)想有一個(gè)非常簡(jiǎn)單的用戶數(shù)據(jù)庫,包括用戶電子信箱和一個(gè)標(biāo)志,用來指示郵件地址是否被彈回。你的數(shù)據(jù)庫程序應(yīng)該包括插入、修改、刪除和查詢等方法

插入方法會(huì)調(diào)用一個(gè)存儲(chǔ)過程將數(shù)據(jù)寫入數(shù)據(jù)庫。為了敘述方便,這里省去了一些細(xì)節(jié),大致的程序如下所示:

public class UserDatabase

{

...

public void insert(User user)

{

PreparedStatement ps = connection.prepareCall("{ call User_insert(?,?) }");

ps.setString(1, user.getEmail());

ps.setString(2, user.isBad());// In real life, this would be a boolean.

ps.executeUpdate();

ps.close();

}

...

}



而我認(rèn)為的測(cè)試代碼應(yīng)為:

public class TestUserDatabase extends TestCase

{

...

public void testInsert()

{

// Insert a test user:

User user = new User("some@email.address");

UserDatabase database = new UserDatabase();

database.insert(user);



// Make sure the data really got there:

User db_user = database.find("some@email.address");

assertTrue("Expected non-null result", db_user != null);

assertEquals("Wrong email", "some@email.address", db_user.getEmail());

assertEquals("Wrong bad flag", false, db_user.isBad());

}

...

}



可能你還有更多測(cè)試代碼。(注意一些測(cè)試,例如對(duì)date類的測(cè)試)。

assertTrue和assertEquals方法進(jìn)行條件測(cè)試。如果測(cè)試失敗,他們將返回診斷消息。其重點(diǎn)是這些測(cè)試都基于一個(gè)測(cè)試框架自動(dòng)執(zhí)行,并給出測(cè)試成敗的標(biāo)志。這些測(cè)試都基于用java語言編寫的測(cè)試框架Junit類(程序附后)。這一框架也能適應(yīng)其他諸如C, C++, Perl, Python, .NET (all languages), PL/SQL, Eiffel, Delphi, VB等語言環(huán)境。

下一個(gè)問題就是:我們有測(cè)試,但我們?cè)鯓颖WC測(cè)試數(shù)據(jù)和實(shí)際數(shù)據(jù)能嚴(yán)格區(qū)分?





三、不同的鑒別方法



在開始之前,我必須指出你最好有一個(gè)測(cè)試用的數(shù)據(jù)庫,你可能更想在非正式的數(shù)據(jù)庫中實(shí)踐我講的東西。

第一種方法是手工在數(shù)據(jù)庫中輸入一些預(yù)先知道的測(cè)試性數(shù)據(jù),例如在郵件地址中輸入“testuser01@test.testing”。如果你正在測(cè)試數(shù)據(jù)庫的查詢功能,你能預(yù)先知道,比如說有五個(gè),數(shù)據(jù)庫記錄是以“@test.testing”結(jié)尾的。

由以上方式插入的數(shù)據(jù)必須由測(cè)試本身進(jìn)行必要的維護(hù)。例如,測(cè)試必須負(fù)責(zé)刪除所建立的測(cè)試數(shù)據(jù),而避免對(duì)實(shí)際數(shù)據(jù)進(jìn)行操作,從而保證整個(gè)數(shù)據(jù)庫處于完好狀態(tài)。

這種方法還是存在以下問題:

l你不得不和其他編程人員進(jìn)行數(shù)據(jù)協(xié)調(diào)——假設(shè)他們也有他們自己的測(cè)試數(shù)據(jù)庫。

l在數(shù)據(jù)庫中有些特殊的數(shù)據(jù)并不正確,如一些特別的郵件地址和被保留餓編號(hào)前綴。

l在某些情況下,你將不能用一些特殊的數(shù)據(jù)來區(qū)分測(cè)試數(shù)據(jù)和實(shí)際數(shù)據(jù),這就比較棘手。例如,某條數(shù)據(jù)由一些整數(shù)型字段構(gòu)成,而作為測(cè)試用的數(shù)值都看起來較為合理。

l你的測(cè)試只限于你為測(cè)試所保留的某些特殊值,這意味著你將小心地選擇那些特殊值。

l如果數(shù)據(jù)對(duì)時(shí)間敏感,那對(duì)數(shù)據(jù)庫的維護(hù)將更為困難。例如,數(shù)據(jù)庫中有產(chǎn)品銷售提議,而該提議只在明確的時(shí)間段里有效。

我曾經(jīng)試著做過修改。例如,在數(shù)據(jù)庫中增加“is_test”字段作為區(qū)分測(cè)試數(shù)據(jù)的標(biāo)志,從而避免特殊值的問題。但由此帶來的問題是,你的測(cè)試代碼將只測(cè)試那些標(biāo)記為測(cè)試的數(shù)據(jù),而你的正式代碼卻要處理那些未標(biāo)記為測(cè)試的數(shù)據(jù)。如果你的測(cè)試在這方面有區(qū)別,你事實(shí)上并不在測(cè)試同一代碼。





四、你需要四個(gè)數(shù)據(jù)庫



有些想法認(rèn)為一個(gè)好的測(cè)試是足夠充分的并能建立測(cè)試所需要的全部數(shù)據(jù)。如果你能在測(cè)試進(jìn)行前就明確知道數(shù)據(jù)庫所處的狀態(tài),測(cè)試可以進(jìn)行一些簡(jiǎn)化。一個(gè)簡(jiǎn)化的方法是建立一個(gè)獨(dú)立的單元測(cè)試數(shù)據(jù)庫用于測(cè)試程序,測(cè)試程序在開始進(jìn)行前清除測(cè)試數(shù)據(jù)庫中的全部數(shù)據(jù)。

在代碼中,你可以編寫一個(gè)dbSetUp方法,如下所示:

public void dbSetUp()

{

// Put the database in a known state:

// (stored procedures would probably be better here)

helper.exec("DELETE FROM SomeSideTable");

helper.exec("DELETE FROM User");



// Insert some commonly-used test cases:

...

}



任何數(shù)據(jù)庫測(cè)試程序都將在做任何事前首先調(diào)用dbSetUp方法,它將使測(cè)試數(shù)據(jù)庫處于一種已知狀態(tài)(大部分情況下是空數(shù)據(jù)庫狀態(tài))。這種做法具有以下的優(yōu)點(diǎn):

l所有的測(cè)試數(shù)據(jù)都在代碼層和其他編程人員進(jìn)行交流,因此沒有必要進(jìn)行外部測(cè)試數(shù)據(jù)協(xié)調(diào)。

l無須測(cè)試用的特殊數(shù)據(jù)的介入。

l簡(jiǎn)單而容易理解的一種方法。

l在每一次測(cè)試前刪除和插入數(shù)據(jù)可能會(huì)花較多時(shí)間,但是由于測(cè)試用的數(shù)據(jù)量相對(duì)較小,我認(rèn)為這種方法比較快捷,特別是在測(cè)試一個(gè)本地?cái)?shù)據(jù)庫時(shí)。

這種做法不利的一面是你需要至少兩個(gè)數(shù)據(jù)庫。但是請(qǐng)記住,他們?cè)诒匾嵌伎梢栽谕粋€(gè)服務(wù)器上運(yùn)行。采用這種方法,我用了四個(gè)數(shù)據(jù)庫,另外兩個(gè)在緊急關(guān)頭時(shí)使用,具體如下:

1. 實(shí)際使用數(shù)據(jù)庫,包含實(shí)際數(shù)據(jù)。在這個(gè)數(shù)據(jù)庫中不進(jìn)行測(cè)試,確保數(shù)據(jù)的完整性。

2. 你的本地開發(fā)數(shù)據(jù)庫,用來進(jìn)行大部分的測(cè)試。

3. 一個(gè)加入一定量數(shù)據(jù)的本地開發(fā)數(shù)據(jù)庫,可能和其他編程人員共享,用來運(yùn)行應(yīng)用程序并檢測(cè)是否能在實(shí)際使用的數(shù)據(jù)庫上運(yùn)行,而不是照搬實(shí)際使用數(shù)據(jù)庫中的全部數(shù)據(jù)。從嚴(yán)格意義上說你可能并不需要這一數(shù)據(jù)庫,但這一數(shù)據(jù)庫能確保應(yīng)用程序在有大量數(shù)據(jù)的數(shù)據(jù)庫中順利運(yùn)行。

4. 一個(gè)發(fā)布數(shù)據(jù)庫,或稱集成數(shù)據(jù)庫,用來在正式發(fā)布前進(jìn)行一系列測(cè)試,從而確保對(duì)所有本地?cái)?shù)據(jù)庫的修改都得到確認(rèn)。如果你一個(gè)人開發(fā),你可以省略這個(gè)數(shù)據(jù)庫,但你必須確保所有對(duì)數(shù)據(jù)結(jié)構(gòu)和存儲(chǔ)過程的修改都在實(shí)際使用數(shù)據(jù)庫中得到確認(rèn)。

在有多個(gè)數(shù)據(jù)庫的情況下,你要確保不同數(shù)據(jù)庫間結(jié)構(gòu)的同步:如果你在測(cè)試數(shù)據(jù)庫中改變表的定義或存儲(chǔ)過程,你必須記得在實(shí)際使用的服務(wù)器上進(jìn)行同樣的修改。發(fā)布數(shù)據(jù)庫的作用就是提醒你進(jìn)行這些修改。另外,我發(fā)現(xiàn)如果代碼控制系統(tǒng)能將提交時(shí)的注釋用郵件形式自動(dòng)發(fā)給整個(gè)開發(fā)組,那將給團(tuán)隊(duì)開發(fā)帶來較大幫助。CVS就能做到這一點(diǎn),我希望你能利用這一功能。





五、在合適的數(shù)據(jù)庫中進(jìn)行測(cè)試



在這種情況下,你必須連接正確的數(shù)據(jù)庫。在實(shí)際使用數(shù)據(jù)庫中進(jìn)行測(cè)試有可能刪除所有的有用數(shù)據(jù),這點(diǎn)令我十分害怕。

有幾種辦法能避免此類悲劇的發(fā)生。例如,比較普遍的做法是將數(shù)據(jù)庫連接設(shè)置記錄在初始文件中,從而明確哪一個(gè)是測(cè)試數(shù)據(jù)庫。你也可以通過初始文件進(jìn)行本地?cái)?shù)據(jù)庫的測(cè)試,而用其他指定方法連接實(shí)際使用數(shù)據(jù)庫。

在java代碼中,初始文件可能如下所示;

myapp.db.url=jdbc:mysql://127.0.0.1/mydatabase

這一連接字符串用來連接數(shù)據(jù)庫。你可以添加第二個(gè)連接字符串來區(qū)分測(cè)試數(shù)據(jù)庫:

myapp.db.url=jdbc:mysql://127.0.0.1/mydatabase

myapp.db.testurl=jdbc:mysql://127.0.0.1/my_test_database

在測(cè)試代碼中,你可以檢查并確保在連接到測(cè)試數(shù)據(jù)庫后應(yīng)用程序才能繼續(xù)運(yùn)行:

public void dbSetUp()

{

 String test_db = InitProperties.get("myapp.db.testurl");

 String db = InitProperties.get("myapp.db.url");



 if (test_db == null)

 abort("No test database configured");



 if (test_db.equals(db))

 {

// All is well: the database we're connecting to is the

// same as the database identified as "for testing"

 }

 else

 {

abort("Will not run tests against a non-test database");

 }

}



另一個(gè)技巧是,如果你有一個(gè)本地測(cè)試數(shù)據(jù)庫,測(cè)試程序能通過提供IP地址或主機(jī)名進(jìn)行檢測(cè)。如果不是“l(fā)ocalhost/127.0.0.1”,這就有連接在實(shí)際使用數(shù)據(jù)庫上進(jìn)行測(cè)試的風(fēng)險(xiǎn)。







六、關(guān)于測(cè)試日期的體會(huì)



如果你想存儲(chǔ)日期信息,你大概想確認(rèn)你存的日期信息是否正確。請(qǐng)注意以下幾點(diǎn)。

首先先問自己,是誰創(chuàng)建該日期。如果是你的應(yīng)用程序,那驗(yàn)證比較簡(jiǎn)單,因?yàn)槟憧梢酝ㄟ^查看數(shù)據(jù)庫中的具體日期進(jìn)行比較。如果是數(shù)據(jù)庫本身創(chuàng)建該日期,可能作為一個(gè)缺省字段,那你可能就會(huì)有些問題。例如,你能確保你代碼所代表的時(shí)區(qū)和數(shù)據(jù)庫的時(shí)區(qū)一致嗎?從沒有聽說過數(shù)據(jù)庫是以格林尼治標(biāo)準(zhǔn)時(shí)間為準(zhǔn)顯示時(shí)間和日期的。你能確保運(yùn)行應(yīng)用程序的計(jì)算機(jī)上的時(shí)間和數(shù)據(jù)庫所在計(jì)算機(jī)上的時(shí)間保持一致嗎?如果不是,你必須在進(jìn)行時(shí)間的比較時(shí)留出一定的誤差。

如果你遇到這些情況,有些事是你可以做的:

如果你預(yù)先知道所用的時(shí)區(qū),在測(cè)試前將所有日期和時(shí)間全部轉(zhuǎn)換成那個(gè)時(shí)區(qū)的日期和時(shí)間。

在比較時(shí)間時(shí)設(shè)立一定的誤差,比如說幾分鐘、幾小時(shí)或幾個(gè)月。看上去缺乏說服力,但至少它能捕獲諸如日期為空或1970年1月1日等錯(cuò)誤。



七、總結(jié)

在本文中,我想說:

單元數(shù)據(jù)庫測(cè)試是一件值得做的事;

如果你能給一系列測(cè)試程序一個(gè)對(duì)應(yīng)的數(shù)據(jù)庫,測(cè)試本身并不非�?膳�。

還有其他方法能解決這一問題。我還不能確信模仿對(duì)象(Mock Object)這一方法。就我對(duì)這一方法的理解,模仿對(duì)象模擬了一個(gè)系統(tǒng)中間層(在本文中,是數(shù)據(jù)庫操作系統(tǒng)),使得模仿的數(shù)據(jù)庫總能返回你想要的數(shù)據(jù)。我比較欣賞這一概念,它鼓勵(lì)你對(duì)測(cè)試進(jìn)行分層,可能劃分成SQL方面的測(cè)試和Java語言方面的測(cè)試,從而對(duì)模仿的ResultSet對(duì)象進(jìn)行測(cè)試。

我比較關(guān)注那些能導(dǎo)致一次能使兩個(gè)或兩個(gè)以上的數(shù)據(jù)表產(chǎn)生變化的操作。在這種情況下,用模仿對(duì)象方法進(jìn)行數(shù)據(jù)庫的維護(hù)和實(shí)現(xiàn)比較困難。當(dāng)然,我還要找到一種好方法進(jìn)行數(shù)據(jù)庫中SQL方面的測(cè)試,從而確認(rèn)數(shù)據(jù)被正確地存儲(chǔ)到數(shù)據(jù)庫中。



主站蜘蛛池模板: 青青青国产手机在线播放 | 亚洲欧美v视色一区二区 | 日本一区二区在线播放 | 伊人精品视频 | 中文字幕色综合久久 | 青青草成人免费在线视频 | 色成网 | 在线视频日韩精品 | 婷婷综合久久中文字幕一本 | 日本三级香港三级人妇99 | 亚洲欧洲精品久久 | 四虎国产精品永久在线看 | 日日噜噜噜夜夜爽爽狠狠 | 在线看日本吃奶孕交 | 欧美自拍视频 | 日韩特级| 人妖欧美一区二区三区四区 | 天美传媒一区二区三区 | 最新在线精品国自产拍网站 | 欧美亚洲国产专区在线app | 欧美性生活视频免费播放网址大全观看 | 色综合天天综合网国产成人 | 日韩精品一区二区三区乱码 | 日韩专区一区 | 天天天天做夜夜夜夜 | 青草娱乐极品免费视频 | 特级欧美老少乱配 | 亚洲国产成人久久综合一区77 | 一级女性全黄久久生活片 | 性荡视频播放器在线视频播放 | 日本三级视频网站 | 日韩精品一区二区三区 在线观看 | 青草视频入口 在线观看 | 天天好b | 青草网| 青青草激情视频 | 日韩成人免费 | 日本午夜视频 | 日本高清视频在线播放 | 午夜视频在线观看一区 | 亚洲乱码中文字幕久久 |