檢測(cè)認(rèn)證人脈交流通訊錄
單元測(cè)試、靜態(tài)測(cè)試、代碼分析掃描
這真不是您需要的服務(wù)?
直接提問 | 回首頁搜
- 單元測(cè)試
服務(wù)熱線:400-669-0203 020-29178595 QQ2557064750 2649046091 http://www.simou.net.cn/ http://www.innor.org/
單元測(cè)試(unit testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。對(duì)于單元測(cè)試中單元的含義,一般來說,要根據(jù)實(shí)際情況去判定其具體含義,如C語言中單元指一個(gè)函數(shù),Java里單元指一個(gè)類,圖形化的軟件中可以指一個(gè)窗口或一個(gè)菜單等。總的來說,單元就是人為規(guī)定的最小的被測(cè)功能模塊。單元測(cè)試是在軟件開發(fā)過程中要進(jìn)行的最低級(jí)別的測(cè)試活動(dòng),軟件的獨(dú)立單元將在與程序的其他部分相隔離的情況下進(jìn)行測(cè)試。
在一種傳統(tǒng)的結(jié)構(gòu)化編程語言中,比如C,要進(jìn)行測(cè)試的單元一般是函數(shù)或子過程。在像C++這樣的面向?qū)ο蟮恼Z言中, 要進(jìn)行測(cè)試的基本單元是類。對(duì)Ada語言來說,開發(fā)人員可以選擇是在獨(dú)立的過程和函數(shù),還是在Ada包的級(jí)別上進(jìn)行單元測(cè)試。單元測(cè)試的原則同樣被擴(kuò)展到第四代語言(4GL)的開發(fā)中,在這里基本單元被典型地劃分為一個(gè)菜單或顯示界面。
經(jīng)常與單元測(cè)試聯(lián)系起來的另外一些開發(fā)活動(dòng)包括代碼走讀(Code review),靜態(tài)分析(Static analysis)和動(dòng)態(tài)分析(Dynamic analysis)。靜態(tài)分析就是對(duì)軟件的源代碼進(jìn)行研讀,查找錯(cuò)誤或收集一些度量數(shù)據(jù),并不需要對(duì)代碼進(jìn)行編譯和執(zhí)行。動(dòng)態(tài)分析就是通過觀察軟件運(yùn)行時(shí)的動(dòng)作,來提供執(zhí)行跟蹤,時(shí)間分析,以及測(cè)試覆蓋度方面的信息。
基本介紹
單元測(cè)試(模塊測(cè)試)是開發(fā)者編寫的一小段代碼,用于檢驗(yàn)被測(cè)代碼的一個(gè)很小的、很明確的功能是否正確。通常而言,一個(gè)單元測(cè)試是用于判斷某個(gè)特定條件(或者場(chǎng)景)下某個(gè)特定函數(shù)的行為。
折疊編輯本段測(cè)試介紹
在一種傳統(tǒng)的結(jié)構(gòu)化編程語言中,比如C,要進(jìn)行測(cè)試的單元一般是函數(shù)或子過程。在象C++這樣的面向?qū)ο蟮恼Z言中, 要進(jìn)行測(cè)試的基本單元是類。對(duì)Ada語言來說,開發(fā)人員可以選擇是在獨(dú)立的過程和函數(shù),還是在Ada包的級(jí)別上進(jìn)行單元測(cè)試。單元測(cè)試的原則同樣被擴(kuò)展到第四代語言(4GL)的開發(fā)中,在這里基本單元被典型地劃分為一個(gè)菜單或顯示界面。
經(jīng)常與單元測(cè)試聯(lián)系起來的另外一些開發(fā)活動(dòng)包括代碼走讀(Code review),靜態(tài)分析(Static analysis)和動(dòng)態(tài)分析(Dynamic analysis)。靜態(tài)分析就是對(duì)軟件的源代碼進(jìn)行研讀,查找錯(cuò)誤或收集一些度量數(shù)據(jù),并不需要對(duì)代碼進(jìn)行編譯和執(zhí)行。動(dòng)態(tài)分析就是通過觀察軟件運(yùn)行時(shí)的動(dòng)作,來提供執(zhí)行跟蹤,時(shí)間分析,以及測(cè)試覆蓋度方面的信息。
折疊單元測(cè)試
單元測(cè)試(模塊測(cè)試)是開發(fā)者編寫的一小段代碼,用于檢驗(yàn)被測(cè)代碼的一個(gè)很小的、很明確的功能是否正確。通常而言,一個(gè)單元測(cè)試是用于判斷某個(gè)特定條件(或者場(chǎng)景)下某個(gè)特定函數(shù)的行為。例如,你可能把一個(gè)很大的值放入一個(gè)有序list 中去,然后確認(rèn)該值出現(xiàn)在list 的尾部。或者,你可能會(huì)從字符串中刪除匹配某種模式的字符,然后確認(rèn)字符串確實(shí)不再包含這些字符了。
單元測(cè)試是由程序員自己來完成,最終受益的也是程序員自己。可以這么說,程序員有責(zé)任編寫功能代碼,同時(shí)也就有責(zé)任為自己的代碼編寫單元測(cè)試。執(zhí)行單元測(cè)試,就是為了證明這段代碼的行為和我們期望的一致。
工廠在組裝一臺(tái)電視機(jī)之前,會(huì)對(duì)每個(gè)元件都進(jìn)行測(cè)試,這,就是單元測(cè)試。
其實(shí)我們每天都在做單元測(cè)試。你寫了一個(gè)函數(shù),除了極簡單的外,總是要執(zhí)行一下,看看功能是否正常,有時(shí)還要想辦法輸出些數(shù)據(jù),如彈出信息窗口什么的,這,也是單元測(cè)試,把這種單元測(cè)試稱為臨時(shí)單元測(cè)試。只進(jìn)行了臨時(shí)單元測(cè)試的軟件,針對(duì)代碼的測(cè)試很不完整,代碼覆蓋率要超過70%都很困難,未覆蓋的代碼可能遺留大量的細(xì)小的錯(cuò)誤,這些錯(cuò)誤還會(huì)互相影響,當(dāng)BUG暴露出來的時(shí)候難于調(diào)試,大幅度提高后期測(cè)試和維護(hù)成本,也降低了開發(fā)商的競(jìng)爭(zhēng)力。可以說,進(jìn)行充分的單元測(cè)試,是提高軟件質(zhì)量,降低開發(fā)成本的必由之路。
對(duì)于程序員來說,如果養(yǎng)成了對(duì)自己寫的代碼進(jìn)行單元測(cè)試的習(xí)慣,不但可以寫出高質(zhì)量的代碼,而且還能提高編程水平。
要進(jìn)行充分的單元測(cè)試,應(yīng)專門編寫測(cè)試代碼,并與產(chǎn)品代碼隔離。我認(rèn)為,比較簡單的辦法是為產(chǎn)品工程建立對(duì)應(yīng)的測(cè)試工程,為每個(gè)類建立對(duì)應(yīng)的測(cè)試類,為每個(gè)函數(shù)(很簡單的除外)建立測(cè)試函數(shù)。首先就幾個(gè)概念談?wù)勎业目捶ā?
一般認(rèn)為,在結(jié)構(gòu)化程序時(shí)代,單元測(cè)試所說的單元是指函數(shù),在當(dāng)今的面向?qū)ο髸r(shí)代,單元測(cè)試所說的單元是指類。以我的實(shí)踐來看,以類作為測(cè)試單位,復(fù)雜度高,可操作性較差,因此仍然主張以函數(shù)作為單元測(cè)試的測(cè)試單位,但可以用一個(gè)測(cè)試類來組織某個(gè)類的所有測(cè)試函數(shù)。單元測(cè)試不應(yīng)過分強(qiáng)調(diào)面向?qū)ο螅驗(yàn)榫植看a依然是結(jié)構(gòu)化的。單元測(cè)試的工作量較大,簡單實(shí)用高效才是硬道理。
有一種看法是,只測(cè)試類的接口(公有函數(shù)),不測(cè)試其他函數(shù),從面向?qū)ο蠼嵌葋砜矗_實(shí)有其道理,但是,測(cè)試的目的是找錯(cuò)并最終排錯(cuò),因此,只要是包含錯(cuò)誤的可能性較大的函數(shù)都要測(cè)試,跟函數(shù)是否私有沒有關(guān)系。對(duì)于C++來說,可以用一種簡單的方法區(qū)隔需測(cè)試的函數(shù):簡單的函數(shù)如數(shù)據(jù)讀寫函數(shù)的實(shí)現(xiàn)在頭文件中編寫(inline函數(shù)),所有在源文件編寫實(shí)現(xiàn)的函數(shù)都要進(jìn)行測(cè)試(構(gòu)造函數(shù)和析構(gòu)函數(shù)除外)。
折疊為什么要使用單元測(cè)試
我們編寫代碼時(shí),一定會(huì)反復(fù)調(diào)試保證它能夠編譯通過。如果是編譯沒有通過的代碼,沒有任何人會(huì)愿意交付給自己的老板。但代碼通過編譯,只是說明了它的語法正確;我們卻無法保證它的語義也一定正確,沒有任何人可以輕易承諾這段代碼的行為一定是正確的。
幸運(yùn)的是,單元測(cè)試會(huì)為我們的承諾做保證。編寫單元測(cè)試就是用來驗(yàn)證這段代碼的行為是否與我們期望的一致。有了單元測(cè)試,我們可以自信的交付自己的代碼,而沒有任何的后顧之憂。
什么時(shí)候測(cè)試?單元測(cè)試越早越好,早到什么程度?XP開發(fā)理論講究TDD,即測(cè)試驅(qū)動(dòng)開發(fā),先編寫測(cè)試代碼,再進(jìn)行開發(fā)。在實(shí)際的工作中,可以不必過分強(qiáng)調(diào)先什么后什么,重要的是高效和感覺舒適。從老納的經(jīng)驗(yàn)來看,先編寫產(chǎn)品函數(shù)的框架,然后編寫測(cè)試函數(shù),針對(duì)產(chǎn)品函數(shù)的功能編寫測(cè)試用例,然后編寫產(chǎn)品函數(shù)的代碼,每寫一個(gè)功能點(diǎn)都運(yùn)行測(cè)試,隨時(shí)補(bǔ)充測(cè)試用例。所謂先編寫產(chǎn)品函數(shù)的框架,是指先編寫函數(shù)空的實(shí)現(xiàn),有返回值的隨便返回一個(gè)值,編譯通過后再編寫測(cè)試代碼,這時(shí),函數(shù)名、參數(shù)表、返回類型都應(yīng)該確定下來了,所編寫的測(cè)試代碼以后需修改的可能性比較小。
由誰測(cè)試?單元測(cè)試與其他測(cè)試不同,單元測(cè)試可看作是編碼工作的一部分,應(yīng)該由程序員完成,也就是說,經(jīng)過了單元測(cè)試的代碼才是已完成的代碼,提交產(chǎn)品代碼時(shí)也要同時(shí)提交測(cè)試代碼。測(cè)試部門可以作一定程度的審核。
關(guān)于樁代碼,老納認(rèn)為,單元測(cè)試應(yīng)避免編寫樁代碼。樁代碼就是用來代替某些代碼的代碼,例如,產(chǎn)品函數(shù)或測(cè)試函數(shù)調(diào)用了一個(gè)未編寫的函數(shù),可以編寫樁函數(shù)來代替該被調(diào)用的函數(shù),樁代碼也用于實(shí)現(xiàn)測(cè)試隔離。采用由底向上的方式進(jìn)行開發(fā),底層的代碼先開發(fā)并先測(cè)試,可以避免編寫樁代碼,這樣做的好處有:減少了工作量;測(cè)試上層函數(shù)時(shí),也是對(duì)下層函數(shù)的間接測(cè)試;當(dāng)下層函數(shù)修改時(shí),通過回歸測(cè)試可以確認(rèn)修改是否導(dǎo)致上層函數(shù)產(chǎn)生錯(cuò)誤。
在一種傳統(tǒng)的結(jié)構(gòu)化編程語言中,比如C,要進(jìn)行測(cè)試的單元一般是函數(shù)或子過程。在象C++這樣的面向?qū)ο蟮恼Z言中, 要進(jìn)行測(cè)試的基本單元是類。對(duì)Ada語言來說,開發(fā)人員可以選擇是在獨(dú)立的過程和函數(shù),還是在Ada包的級(jí)別上進(jìn)行單元測(cè)試。單元測(cè)試的原則同樣被擴(kuò)展到第四代語言(4GL)的開發(fā)中,在這里基本單元被典型地劃分為一個(gè)菜單或顯示界面。
折疊一些流行的誤解
在明確了什么是單元測(cè)試以后,我們可以進(jìn)行"反調(diào)論證"了。在下面的章節(jié)里,我們列出了一些反對(duì)單元測(cè)試的普遍的論點(diǎn)。然后用充分的理由來證明這些論點(diǎn)是不足取的。
它浪費(fèi)了太多的時(shí)間
測(cè)試工具
現(xiàn)在開始介紹單元測(cè)試工具,分別按編程語言進(jìn)行分組介紹。
折疊C/C++
CppUnit
首先是CppUnit,這是C++單元測(cè)試工具的鼻祖,免費(fèi)的開源的單元測(cè)試框架。由于已有一眾高人寫了不少關(guān)于CppUnit的很好的文章,老納就不現(xiàn)丑了,想了解CppUnit的朋友,建議讀一下Cpluser 所作的《CppUnit測(cè)試框架入門》,。該文也提供了CppUnit的下載地址。
C++Test
然后介紹C++Test,這是Parasoft公司的產(chǎn)品。[C++Test是一個(gè)功能強(qiáng)大的自動(dòng)化C/C++單元級(jí)測(cè)試工具,可以自動(dòng)測(cè)試任何C/C++函數(shù)、類,自動(dòng)生成測(cè)試用例、測(cè)試驅(qū)動(dòng)函數(shù)或樁函數(shù),在自動(dòng)化的環(huán)境下極其容易快速的將單元級(jí)的測(cè)試覆蓋率達(dá)到100%]。[]內(nèi)的文字引自,這是華唐公司的網(wǎng)頁。老納想寫些介紹C++Test的文字,但發(fā)現(xiàn)無法超越華唐公司的網(wǎng)頁上的介紹,所以也就省點(diǎn)事了,想了解C++Test的朋友,建議訪問該公司的網(wǎng)站。華唐公司代理C++Test,想要購買或索取報(bào)價(jià)、試用版都可以找他們。
Visual Unit
最后介紹Visual Unit,簡稱VU,這是國產(chǎn)的單元測(cè)試工具,據(jù)說申請(qǐng)了多項(xiàng)專利,擁有一批創(chuàng)新的技術(shù),不過老納只關(guān)心是不是有用和好用。[自動(dòng)生成測(cè)試代碼 快速建立功能測(cè)試用例 程序行為一目了然 極高的測(cè)試完整性 高效完成白盒覆蓋 快速排錯(cuò) 高效調(diào)試 詳盡的測(cè)試報(bào)告]。[]內(nèi)的文字是VU開發(fā)商的網(wǎng)頁上摘錄的,。前面所述測(cè)試要求:完成功能測(cè)試,完成語句覆蓋、條件覆蓋、分支覆蓋、路徑覆蓋,用VU可以輕松實(shí)現(xiàn),還有一點(diǎn)值得一提:使用VU還能提高編碼的效率,總體來說,在完成單元測(cè)試的同時(shí),編碼調(diào)試的時(shí)間還能大幅度縮短。算了,不想再講了,老納顯擺理論、介紹經(jīng)驗(yàn)還是有興趣的,因?yàn)榭梢詽M足老納好為人師的虛榮心,但介紹工具就覺得索然無味了,畢竟工具好不好用,合不合用,要試過才知道,還是自己去開發(fā)商的網(wǎng)站看吧,可以下載演示版,還有演示課件。
gtest
gtest測(cè)試框架是在不同平臺(tái)上(Linux,Mac OS X,Windows,Cygwin,Windows CE和Symbian)為編寫C++測(cè)試而生成的。它是基于xUnit架構(gòu)的測(cè)試框架,支持自動(dòng)發(fā)現(xiàn)測(cè)試,豐富的斷言集,用戶定義的斷言,death測(cè)試,致命與非致命的失敗,類型參數(shù)化測(cè)試,各類運(yùn)行測(cè)試的選項(xiàng)和XML的測(cè)試報(bào)告。需要詳細(xì)了解的朋友可以參閱《玩轉(zhuǎn)Google單元測(cè)試框架gtest系列》該篇文章。
折疊Java
JUnit
JUnit 是 Java 社區(qū)中知名度最高的單元測(cè)試工具。它誕生于 1997 年,由 Erich Gamma 和 Kent Beck 共同開發(fā)完成。其中 Erich Gamma 是經(jīng)典著作《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書的作者之一,并在 Eclipse 中有很大的貢獻(xiàn);Kent Beck 則是一位極限編程(XP)方面的專家和先驅(qū)。JUnit 設(shè)計(jì)的非常小巧,但是功能卻非常強(qiáng)大。JUnit ——是一個(gè)開發(fā)源代碼的Java測(cè)試框架,用于編寫和運(yùn)行可重復(fù)的測(cè)試。他是用于單元測(cè)試框架體系xUnit的一個(gè)實(shí)例(用于java語言)。主要用于白盒測(cè)試,回歸測(cè)試。
JUnit的好處和JUnit單元測(cè)試編寫原則:
好處:可以使測(cè)試代碼與產(chǎn)品代碼分開;針對(duì)某一個(gè)類的測(cè)試代碼通過較少的改動(dòng)便可以應(yīng)用于另一個(gè)類的測(cè)試;易于集成到測(cè)試人員的構(gòu)建過程中,JUnit和Ant的結(jié)合可以實(shí)施增量開發(fā);JUnit是公開源代碼的,可以進(jìn)行二次開發(fā);可以方便地對(duì)JUnit進(jìn)行擴(kuò)展;
編寫原則:是簡化測(cè)試的編寫,這種簡化包括測(cè)試框架的學(xué)習(xí)和實(shí)際測(cè)試單元的編寫;是使測(cè)試單元保持持久性;是可以利用既有的測(cè)試來編寫相關(guān)的測(cè)試;
有興趣的朋友可以下下來仔細(xì)研究下。
JUnit-addons
對(duì)JUnit的一些補(bǔ)充,比如設(shè)置、獲取被測(cè)試對(duì)象的私有屬性的值,調(diào)用被測(cè)試對(duì)象的私有方法等。
常用類:junitx.util.PrivateAccessor
Spring 測(cè)試框架
可以測(cè)試基于Spring的應(yīng)用,通過配置文件和注解自動(dòng)組裝需要的單元測(cè)試對(duì)象。
提供了一些常用的J2EE Mock對(duì)象,比如HttpSession的Mock類等。
可以支持?jǐn)?shù)據(jù)庫自動(dòng)回滾,以防止對(duì)數(shù)據(jù)庫的單元測(cè)試(插入,刪除等)不可重復(fù)執(zhí)行,防止修改數(shù)據(jù)庫狀態(tài)等。
DJUnit
通過代碼自動(dòng)產(chǎn)生Mock對(duì)象,省去了自己手動(dòng)編寫N多的Mock類。
此外,它的Eclipse插件還可以做到測(cè)試覆蓋率、分支統(tǒng)計(jì)。
EasyMock
功能同DJUnit,也是通過編程自動(dòng)Mock掉與測(cè)試對(duì)象無關(guān)的類,方法。
折疊編輯本段相關(guān)介紹
折疊范疇
如果要給單元測(cè)試定義一個(gè)明確的范疇,指出哪些功能是屬于單元測(cè)試,這似乎很難。但下面討論的四個(gè)問題,基本上可以說明單元測(cè)試的范疇,單元測(cè)試所要做的工作。
1、 它的行為和我期望的一致嗎?
這是單元測(cè)試最根本的目的,我們就是用單元測(cè)試的代碼來證明它所做的就是我們所期望的。
2、 它的行為一直和我期望的一致嗎?
編寫單元測(cè)試,如果只測(cè)試代碼的一條正確路徑,讓它正確走一遍,并不算是真正的完成。軟件開發(fā)是一個(gè)項(xiàng)復(fù)雜的工程,在測(cè)試某段代碼的行為是否和你的期望一致時(shí),你需要確認(rèn):在任何情況下,這段代碼是否都和你的期望一致;譬如參數(shù)很可疑、硬盤沒有剩余空間、緩沖區(qū)溢出、網(wǎng)絡(luò)掉線的時(shí)候。
3、 我可以依賴單元測(cè)試嗎?
不能依賴的代碼是沒有多大用處的。既然單元測(cè)試是用來保證代碼的正確性,那么單元測(cè)試也一定要值得依賴。
4、 單元測(cè)試說明我的意圖了嗎?
單元測(cè)試能夠幫我們充分了解代碼的用法,從效果上而言,單元測(cè)試就像是能執(zhí)行的文檔,說明了在你用各種條件調(diào)用代碼時(shí),你所能期望這段代碼完成的功能。
折疊不寫測(cè)試的借口
到這里,我們已經(jīng)列舉了使用單元測(cè)試的種種理由。也許,每個(gè)人都同意,是的,該做更多的測(cè)試。這種人人同意的事情還多著呢,是的,該多吃蔬菜,該戒煙,該多休息,該多鍛煉……這并不意味著我們中的所有人都會(huì)這么去做,不是嗎?
1、 編寫單元測(cè)試太花時(shí)間了。
我們知道,在開發(fā)時(shí)越早發(fā)現(xiàn)BUG,就能節(jié)省更多的時(shí)間,降低更多的風(fēng)險(xiǎn)。
下圖表摘自<<實(shí)用軟件度量>>(Capers Jones,McGraw-Hill 1991),它列出了準(zhǔn)備測(cè)試,執(zhí)行測(cè)試,和修改缺陷所花費(fèi)的時(shí)間(以一個(gè)功能點(diǎn)為基準(zhǔn)),這些數(shù)據(jù)顯示單元測(cè)試的成本效率大約是集成測(cè)試的兩倍,是系統(tǒng)測(cè)試的三倍(參見條形圖)。
術(shù)語:域測(cè)試(Field test)意思是在軟件投入使用以后,針對(duì)某個(gè)領(lǐng)域所作的所有測(cè)試活動(dòng)。
如果你仍然認(rèn)為在編寫產(chǎn)品代碼的時(shí)候,還是沒有時(shí)間編寫測(cè)試代碼,那么請(qǐng)先考慮下面這些問題:
1)、對(duì)于所編寫的代碼,你在調(diào)試上面花了多少時(shí)間。
2)、對(duì)于以前你自認(rèn)為正確的代碼,而實(shí)際上這些代碼卻存在重大的bug,你花了多少時(shí)間在重新確認(rèn)這些代碼上面。
3)、對(duì)于一個(gè)別人報(bào)告的bug,你花了多少時(shí)間才找出導(dǎo)致這個(gè)bug 的源碼位置。
回答完這些問題,你一定不再以“太花時(shí)間”作為拒絕單元測(cè)試的借口。
2、 運(yùn)行測(cè)試的時(shí)間太長了。
合適的測(cè)試是不會(huì)讓這種情況發(fā)生的。實(shí)際上,大多數(shù)測(cè)試的執(zhí)行都是非常快的,因此你在幾秒之內(nèi)就可以運(yùn)行成千上萬個(gè)測(cè)試。但是有時(shí)某些測(cè)試會(huì)花費(fèi)很長的時(shí)間。這時(shí),需要把這些耗時(shí)的測(cè)試和其他測(cè)試分開。通常可以每天運(yùn)行這種測(cè)試一次,或者幾天一次。
3、 測(cè)試代碼并不是我的工作。
你的工作就是保證代碼能夠正確的完成你的行為,恰恰相反,測(cè)試代碼正是你不可缺少的工作。
4、 我并不清楚代碼的行為,所以也就無從測(cè)試。
如果你實(shí)在不清楚代碼的行為,那么估計(jì)現(xiàn)在并不是編碼的時(shí)候。如果你并不知道代碼的行為,那么你又如何知道你編寫的代碼是正確的呢
5、 但是這些代碼都能夠編譯通過。
我們前面已經(jīng)說過,代碼通過編譯只是驗(yàn)證它的語法通過。但并不能保證它的行為就一定正確。
6、 公司請(qǐng)我來是為了寫代碼,而不是寫測(cè)試。
公司付給你薪水是為了讓你編寫產(chǎn)品代碼,而單元測(cè)試大體上是一個(gè)工具,是一個(gè)和編輯器、開發(fā)環(huán)境、編譯器等處于同一位置的工具。
7、 如果我讓測(cè)試員或者QA(Quality Assurance)人員沒有工作,那么我會(huì)覺得很內(nèi)疚。
你并不需要擔(dān)心這些。請(qǐng)記住,我們?cè)诖酥皇钦務(wù)搯卧獪y(cè)試,而它只是一種針對(duì)源碼的、低層次的,為程序員而設(shè)計(jì)的測(cè)試。在整個(gè)項(xiàng)目中,還有其他的很多測(cè)試需要這些人來完成,如:功能測(cè)試、驗(yàn)收測(cè)試、性能測(cè)試、環(huán)境測(cè)試、有效性測(cè)試、正確性測(cè)試、正規(guī)分析等等。
8、 我的公司并不會(huì)讓我在真實(shí)系統(tǒng)中運(yùn)行單元測(cè)試。
我們所討論的只是針對(duì)開發(fā)者的單元測(cè)試。也就是說,如果你可以在其他的環(huán)境下(例如在正式的產(chǎn)品系統(tǒng)中)運(yùn)行這些測(cè)試的話,那么它們就不再是單元測(cè)試,而是其他類型的測(cè)試了。實(shí)際上,你可以在你的本機(jī)運(yùn)行單元測(cè)試,使用你自己的數(shù)據(jù)庫,或者使用mock 對(duì)象。
一旦編碼完成,開發(fā)人員總是會(huì)迫切希望進(jìn)行軟件的集成工作,這樣他們就能夠看到實(shí)際的系統(tǒng)開始啟動(dòng)工作了。這在外表上看來是一項(xiàng)明顯的進(jìn)步,而象單元測(cè)試這樣的活動(dòng)也許會(huì)被看作是通往這個(gè)階段點(diǎn)的道路上的障礙, 推遲了對(duì)整個(gè)系統(tǒng)進(jìn)行聯(lián)調(diào)這種真正有意思的工作啟動(dòng)的時(shí)間。
在這種開發(fā)步驟中,真實(shí)意義上的進(jìn)步被外表上的進(jìn)步取代了。系統(tǒng)能夠正常工作的可能性是很小的,更多的情況是充滿了各式各樣的Bug。在實(shí)踐中,這樣一種開發(fā)步驟常常會(huì)導(dǎo)致這樣的結(jié)果:軟件甚至無法運(yùn)行。更進(jìn)一步的結(jié)果是大量的時(shí)間將被花費(fèi)在跟蹤那些包含在獨(dú)立單元里的簡單的Bug上面,在個(gè)別情況下,這些Bug也許是瑣碎和微不足道的,但是總的來說,他們會(huì)導(dǎo)致在軟件集成為一個(gè)系統(tǒng)時(shí)增加額外的工期, 而且當(dāng)這個(gè)系統(tǒng)投入使用時(shí)也無法確保它能夠可靠運(yùn)行。
在實(shí)踐工作中,進(jìn)行了完整計(jì)劃的單元測(cè)試和編寫實(shí)際的代碼所花費(fèi)的精力大致上是相同的。一旦完成了這些單元測(cè)試工作,很多Bug將被糾正,在確信他們手頭擁有穩(wěn)定可靠的部件的情況下,開發(fā)人員能夠進(jìn)行更高效的系統(tǒng)集成工作。這才是真實(shí)意義上的進(jìn)步,所以說完整計(jì)劃下的單元測(cè)試是對(duì)時(shí)間的更高效的利用。而調(diào)試人員的不受控和散漫的工作方式只會(huì)花費(fèi)更多的時(shí)間而取得很少的好處。
使用AdaTEST和Cantata這樣的支持工具可以使單元測(cè)試更加簡單和有效。但這不是必須的,單元測(cè)試即使是在沒有工具支持的情況下也是一項(xiàng)非常有意義的活動(dòng)。
它僅僅是證明這些代碼做了什么
這是那些沒有首先為每個(gè)單元編寫一個(gè)詳細(xì)的規(guī)格說明而直接跳到編碼階段的開發(fā)人員提出的一條普遍的抱怨, 當(dāng)編碼完成以后并且面臨代碼測(cè)試任務(wù)的時(shí)候,他們就閱讀這些代碼并找出它實(shí)際上做了什么,把他們的測(cè)試工作基于已經(jīng)寫好的代碼的基礎(chǔ)上。當(dāng)然,他們無法證明任何事情。所有的這些測(cè)試工作能夠表明的事情就是編譯器工作正常。是的,他們也許能夠抓住(希望能夠)罕見的編譯器Bug,但是他們能夠做的僅僅是這些。
如果他們首先寫好一個(gè)詳細(xì)的規(guī)格說明,測(cè)試能夠以規(guī)格說明為基礎(chǔ)。代碼就能夠針對(duì)它的規(guī)格說明,而不是針對(duì)自身進(jìn)行測(cè)試。這樣的測(cè)試仍然能夠抓住編譯器的Bug,同時(shí)也能找到更多的編碼錯(cuò)誤,甚至是一些規(guī)格說明中的錯(cuò)誤。好的規(guī)格說明可以使測(cè)試的質(zhì)量更高,所以最后的結(jié)論是高質(zhì)量的測(cè)試需要高質(zhì)量的規(guī)格說明。
在實(shí)踐中會(huì)出現(xiàn)這樣的情況:一個(gè)開發(fā)人員要面對(duì)測(cè)試一個(gè)單元時(shí)只給出單元的代碼而沒有規(guī)格說明這樣吃力不討好的任務(wù)。你怎樣做才會(huì)有更多的收獲,而不僅僅是發(fā)現(xiàn)編譯器的Bug?第一步是理解這個(gè)單元原本要做什么, --- 不是它實(shí)際上做了什么。比較有效的方法是倒推出一個(gè)概要的規(guī)格說明。這個(gè)過程的主要輸入條件是要閱讀那些程序代碼和注釋, 主要針對(duì)這個(gè)單元, 及調(diào)用它和被它調(diào)用的相關(guān)代碼。畫出流程圖是非常有幫助的,你可以用手工或使用某種工具。可以組織對(duì)這個(gè)概要規(guī)格說明的走讀(Review),以確保對(duì)這個(gè)單元的說明沒有基本的錯(cuò)誤, 有了這種最小程度的代碼深層說明,就可以用它來設(shè)計(jì)單元測(cè)試了。
我是個(gè)很棒的程序員, 我是不是可以不進(jìn)行單元測(cè)試?
在每個(gè)開發(fā)組織中都至少有一個(gè)這樣的開發(fā)人員,他非常擅長于編程,他們開發(fā)的軟件總是在第一時(shí)間就可以正常運(yùn)行,因此不需要進(jìn)行測(cè)試。你是否經(jīng)常聽到這樣的借口?
折疊測(cè)試用例設(shè)計(jì)
下面談?wù)劀y(cè)試用例設(shè)計(jì)。前面已經(jīng)說了,測(cè)試用例的核心是輸入數(shù)據(jù)。預(yù)期輸出是依據(jù)輸入數(shù)據(jù)和程序功能來確定的,也就是說,對(duì)于某一程序,輸入數(shù)據(jù)確定了,預(yù)期輸出也就可以確定了,至于生成/銷毀被測(cè)試對(duì)象和運(yùn)行測(cè)試的語句,是所有測(cè)試用例都大同小異的,因此,我們討論測(cè)試用例時(shí),只討論輸入數(shù)據(jù)。
前面說過,輸入數(shù)據(jù)包括四類:參數(shù)、成員變量、全局變量、IO媒體,這四類數(shù)據(jù)中,只要所測(cè)試的程序需要執(zhí)行讀操作的,就要設(shè)定其初始值,其中,前兩類比較常用,后兩類較少用。顯然,把輸入數(shù)據(jù)的所有可能取值都進(jìn)行測(cè)試,是不可能也是無意義的,我們應(yīng)該用一定的規(guī)則選擇有代表性的數(shù)據(jù)作為輸入數(shù)據(jù),主要有三種:正常輸入,邊界輸入,非法輸入,每種輸入還可以分類,也就是平常說的等價(jià)類法,每類取一個(gè)數(shù)據(jù)作為輸入數(shù)據(jù),如果測(cè)試通過,可以肯定同類的其他輸入也是可以通過的。下面舉例說明:
正常輸入
例如字符串的Trim函數(shù),功能是將字符串前后的空格去除,那么正常的輸入可以有四類:前面有空格;后面有空格;前后均有空格;前后均無空格。
邊界輸入
上例中空字符串可以看作是邊界輸入。
再如一個(gè)表示年齡的參數(shù),它的有效范圍是0-100,那么邊界輸入有兩個(gè):0和100。
非法輸入
非法輸入是正常取值范圍以外的數(shù)據(jù),或使代碼不能完成正常功能的輸入,如上例中表示年齡的參數(shù),小于0或大于100都是非法輸入,再如一個(gè)進(jìn)行文件操作的函數(shù),非法輸入有這么幾類:文件不存在;目錄不存在;文件正在被其他程序打開;權(quán)限錯(cuò)誤。
如果函數(shù)使用了外部數(shù)據(jù),則正常輸入是肯定會(huì)有的,而邊界輸入和非法輸入不是所有函數(shù)都有。一般情況下,即使沒有設(shè)計(jì)文檔,考慮以上三種輸入也可以找出函數(shù)的基本功能點(diǎn)。實(shí)際上,單元測(cè)試與代碼編寫是“一體兩面”的關(guān)系,編碼時(shí)對(duì)上述三種輸入都是必須考慮的,否則代碼的健壯性就會(huì)成問題。
白盒覆蓋
上面所說的測(cè)試數(shù)據(jù)都是針對(duì)程序的功能來設(shè)計(jì)的,就是所謂的黑盒測(cè)試。單元測(cè)試還需要從另一個(gè)角度來設(shè)計(jì)測(cè)試數(shù)據(jù),即針對(duì)程序的邏輯結(jié)構(gòu)來設(shè)計(jì)測(cè)試用例,就是所謂的白盒測(cè)試。在老納看來,如果黑盒測(cè)試是足夠充分的,那么白盒測(cè)試就沒有必要,可惜“足夠充分”只是一種理想狀態(tài),例如:真的是所有功能點(diǎn)都測(cè)試了嗎?程序的功能點(diǎn)是人為的定義,常常是不全面的;各個(gè)輸入數(shù)據(jù)之間,有些組合可能會(huì)產(chǎn)生問題,怎樣保證這些組合都經(jīng)過了測(cè)試?難于衡量測(cè)試的完整性是黑盒測(cè)試的主要缺陷,而白盒測(cè)試恰恰具有易于衡量測(cè)試完整性的優(yōu)點(diǎn),兩者之間具有極好的互補(bǔ)性,例如:完成功能測(cè)試后統(tǒng)計(jì)語句覆蓋率,如果語句覆蓋未完成,很可能是未覆蓋的語句所對(duì)應(yīng)的功能點(diǎn)未測(cè)試。
白盒測(cè)試針對(duì)程序的邏輯結(jié)構(gòu)設(shè)計(jì)測(cè)試用例,用邏輯覆蓋率來衡量測(cè)試的完整性。邏輯單位主要有:語句、分支、條件、條件值、條件值組合,路徑。語句覆蓋就是覆蓋所有的語句,其他類推。另外還有一種判定條件覆蓋,其實(shí)是分支覆蓋與條件覆蓋的組合,在此不作討論。跟條件有關(guān)的覆蓋就有三種,解釋一下:條件覆蓋是指覆蓋所有的條件表達(dá)式,即所有的條件表達(dá)式都至少計(jì)算一次,不考慮計(jì)算結(jié)果;條件值覆蓋是指覆蓋條件的所有可能取值,即每個(gè)條件的取真值和取假值都要至少計(jì)算一次;條件值組合覆蓋是指覆蓋所有條件取值的所有可能組合。老納做過一些粗淺的研究,發(fā)現(xiàn)與條件直接有關(guān)的錯(cuò)誤主要是邏輯操作符錯(cuò)誤,例如:||寫成&&,漏了寫!什么的,采用分支覆蓋與條件覆蓋的組合,基本上可以發(fā)現(xiàn)這些錯(cuò)誤,另一方面,條件值覆蓋與條件值組合覆蓋往往需要大量的測(cè)試用例,因此,在老納看來,條件值覆蓋和條件值組合覆蓋的效費(fèi)比偏低。老納認(rèn)為效費(fèi)比較高且完整性也足夠的測(cè)試要求是這樣的:完成功能測(cè)試,完成語句覆蓋、條件覆蓋、分支覆蓋、路徑覆蓋。做過單元測(cè)試的朋友恐怕會(huì)對(duì)老納提出的測(cè)試要求給予一個(gè)字的評(píng)價(jià):暈!或者兩個(gè)字的評(píng)價(jià):狂暈!因?yàn)檫@似乎是不可能的要求,要達(dá)到這種測(cè)試完整性,其測(cè)試成本是不可想象的,不過,出家人不打逛語,老納之所以提出這種測(cè)試要求,是因?yàn)槔靡恍┕ぞ撸梢栽谳^低的成本下達(dá)到這種測(cè)試要求,后面將會(huì)作進(jìn)一步介紹。
關(guān)于白盒測(cè)試用例的設(shè)計(jì),程序測(cè)試領(lǐng)域的書籍一般都有講述,普通方法是畫出程序的邏輯結(jié)構(gòu)圖如程序流程圖或控制流圖,根據(jù)邏輯結(jié)構(gòu)圖設(shè)計(jì)測(cè)試用例,這些是純粹的白盒測(cè)試,不是老納想推薦的方式。老納所推薦的方法是:先完成黑盒測(cè)試,然后統(tǒng)計(jì)白盒覆蓋率,針對(duì)未覆蓋的邏輯單位設(shè)計(jì)測(cè)試用例覆蓋它,例如,先檢查是否有語句未覆蓋,有的話設(shè)計(jì)測(cè)試用例覆蓋它,然后用同樣方法完成條件覆蓋、分支覆蓋和路徑覆蓋,這樣的話,既檢驗(yàn)了黑盒測(cè)試的完整性,又避免了重復(fù)的工作,用較少的時(shí)間成本達(dá)到非常高的測(cè)試完整性。不過,這些工作可不是手工能完成的,必須借助于工具,后面會(huì)介紹可以完成這些工作的測(cè)試工具。
在真實(shí)世界里,每個(gè)人都會(huì)犯錯(cuò)誤。即使某個(gè)開發(fā)人員可以抱著這種態(tài)度在很少的一些簡單的程序中應(yīng)付過去。但真正的軟件系統(tǒng)是非常復(fù)雜的。真正的軟件系統(tǒng)不可以寄希望于沒有進(jìn)行廣泛的測(cè)試和Bug修改過程就可以正常工作。
編碼不是一個(gè)可以一次性通過的過程。在真實(shí)世界中,軟件產(chǎn)品必須進(jìn)行維護(hù)以對(duì)操作需求的改變作出反應(yīng), 并且要對(duì)最初的開發(fā)工作遺留下來的Bug進(jìn)行修改。你希望依靠那些原始作者進(jìn)行修改嗎? 這些制造出這些未經(jīng)測(cè)試的原始代碼的資深專家們還會(huì)繼續(xù)在其他地方制造這樣的代碼。在開發(fā)人員做出修改后進(jìn)行可重復(fù)的單元測(cè)試可以避免產(chǎn)生那些令人不快的負(fù)作用。
不管怎樣, 集成測(cè)試將會(huì)抓住所有的Bug
我們已經(jīng)在前面的討論中從一個(gè)側(cè)面對(duì)這個(gè)問題進(jìn)行了部分的闡述。這個(gè)論點(diǎn)不成立的原因在于規(guī)模越大的代碼集成意味著復(fù)雜性就越高。如果軟件的單元沒有事先進(jìn)行測(cè)試,開發(fā)人員很可能會(huì)花費(fèi)大量的時(shí)間僅僅是為了使軟件能夠運(yùn)行,而任何實(shí)際的測(cè)試方案都無法執(zhí)行。
一旦軟件可以運(yùn)行了,開發(fā)人員又要面對(duì)這樣的問題:在考慮軟件全局復(fù)雜性的前提下對(duì)每個(gè)單元進(jìn)行全面的測(cè)試。這是一件非常困難的事情,甚至在創(chuàng)造一種單元調(diào)用的測(cè)試條件的時(shí)候,要全面的考慮單元的被調(diào)用時(shí)的各種入口參數(shù)。在軟件集成階段,對(duì)單元功能全面測(cè)試的復(fù)雜程度遠(yuǎn)遠(yuǎn)的超過獨(dú)立進(jìn)行的單元測(cè)試過程。
最后的結(jié)果是測(cè)試將無法達(dá)到它所應(yīng)該有的全面性。一些缺陷將被遺漏,并且很多Bug將被忽略過去。
讓我們類比一下,假設(shè)我們要清洗一臺(tái)已經(jīng)完全裝配好的食物加工機(jī)器!無論你噴了多少水和清潔劑,一些食物的小碎片還是會(huì)粘在機(jī)器的死角位置,只有任其腐爛并等待以后再想辦法。但我們換個(gè)角度想想,如果這臺(tái)機(jī)器是拆開的, 這些死角也許就不存在或者更容易接觸到了,并且每一部分都可以毫不費(fèi)力的進(jìn)行清洗。
折疊成本效率不高
一個(gè)特定的開發(fā)組織或軟件應(yīng)用系統(tǒng)的測(cè)試水平取決于對(duì)那些未發(fā)現(xiàn)的Bug的潛在后果的重視程度。這種后果的嚴(yán)重程度可以從一個(gè)Bug引起的小小的不便到發(fā)生多次的死機(jī)的情況。這種后果可能常常會(huì)被軟件的開發(fā)人員所忽視(但是用戶可不會(huì)這樣),這種情況會(huì)長期的損害這些向用戶提交帶有Bug的軟件的開發(fā)組織的信譽(yù),并且會(huì)導(dǎo)致對(duì)未來的市場(chǎng)產(chǎn)生負(fù)面的影響。相反地,一個(gè)可靠的軟件系統(tǒng)的良好的聲譽(yù)將有助于一個(gè)開發(fā)組織獲取未來的市場(chǎng)。
很多研究成果表明,無論什么時(shí)候作出修改都要進(jìn)行完整的回歸測(cè)試,在生命周期中盡早地對(duì)軟件產(chǎn)品進(jìn)行測(cè)試將使效率和質(zhì)量得到最好的保證。Bug發(fā)現(xiàn)的越晚,修改它所需的費(fèi)用就越高,因此從經(jīng)濟(jì)角度來看, 應(yīng)該盡可能早的查找和修改Bug。在修改費(fèi)用變的過高之前,單元測(cè)試是一個(gè)在早期抓住Bug的機(jī)會(huì)。
相比后階段的測(cè)試,單元測(cè)試的創(chuàng)建更簡單,維護(hù)更容易,并且可以更方便的進(jìn)行重復(fù)。從全程的費(fèi)用來考慮, 相比起那些復(fù)雜且曠日持久的集成測(cè)試,或是不穩(wěn)定的軟件系統(tǒng)來說,單元測(cè)試所需的費(fèi)用是很低的。
折疊結(jié)論
經(jīng)驗(yàn)表明一個(gè)盡責(zé)的單元測(cè)試方法將會(huì)在軟件開發(fā)的某個(gè)階段發(fā)現(xiàn)很多的Bug,并且修改它們的成本也很低。在軟件開發(fā)的后期階段,Bug的發(fā)現(xiàn)并修改將會(huì)變得更加困難,并要消耗大量的時(shí)間和開發(fā)費(fèi)用。無論什么時(shí)候作出修改都要進(jìn)行完整的回歸測(cè)試,在生命周期中盡早地對(duì)軟件產(chǎn)品進(jìn)行測(cè)試將使效率和質(zhì)量得到最好的保證。在提供了經(jīng)過測(cè)試的單元的情況下,系統(tǒng)集成過程將會(huì)大大地簡化。開發(fā)人員可以將精力集中在單元之間的交互作用和全局的功能實(shí)現(xiàn)上,而不是陷入充滿很多Bug的單元之中不能自拔。
使測(cè)試工作的效力發(fā)揮到最大化的關(guān)鍵在于選擇正確的測(cè)試策略,這其中包含了完全的單元測(cè)試的概念,以及對(duì)測(cè)試過程的良好的管理,還有適當(dāng)?shù)厥褂孟驛daTEST和Cantata這樣的工具來支持測(cè)試過程。這些活動(dòng)可以產(chǎn)生這樣的結(jié)果:在花費(fèi)更低的開發(fā)費(fèi)用的情況下得到更穩(wěn)定的軟件。更進(jìn)一步的好處是簡化了維護(hù)過程并降低了生命周期的費(fèi)用。有效的單元測(cè)試是推行全局質(zhì)量文化的一部分,而這種質(zhì)量文化將會(huì)為軟件開發(fā)者帶來無限的商機(jī)。
折疊優(yōu)點(diǎn)一
它是一種驗(yàn)證行為。
程序中的每一項(xiàng)功能都是測(cè)試來驗(yàn)證它的正確性。它為以后的開發(fā)提供支援。就算是開發(fā)后期,我們也可以輕松的增加功能或更改程序結(jié)構(gòu),而不用擔(dān)心這個(gè)過程中會(huì)破壞重要的東西。而且它為代碼的重構(gòu)提供了保障。這樣,我們就可以更自由的對(duì)程序進(jìn)行改進(jìn)。
折疊優(yōu)點(diǎn)二
它是一種設(shè)計(jì)行為。
編寫單元測(cè)試將使我們從調(diào)用者觀察、思考。特別是先寫測(cè)試(test-first),迫使我們把程序設(shè)計(jì)成易于調(diào)用和可測(cè)試的,即迫使我們解除軟件中的耦合。
折疊優(yōu)點(diǎn)三
它是一種編寫文檔的行為。
單元測(cè)試是一種無價(jià)的文檔,它是展示函數(shù)或類如何使用的最佳文檔。這份文檔是可編譯、可運(yùn)行的,并且它保持最新,永遠(yuǎn)與代碼同步。
折疊優(yōu)點(diǎn)四
它具有回歸性。
自動(dòng)化的單元測(cè)試避免了代碼出現(xiàn)回歸,編寫完成之后,可以隨時(shí)隨地的快速運(yùn)行測(cè)試。
軟件檢測(cè)服務(wù)中心
曾先生
- [聯(lián)系時(shí)請(qǐng)說明來自 檢測(cè)通]
- 聯(lián)系方式:
-
請(qǐng)點(diǎn)擊查看電話
- 地址:
- 廣州市天河區(qū)東圃大馬路購物中心B區(qū)商務(wù)區(qū)1106
日韩av一区二区在线播放|
婷婷激情小说网|
亚洲精品天堂成人片av在线播放|
亚洲一级片免费观看|
日本一区二区免费视频|
超碰在线人人爱|
免费看的av网站|
黄色片在线免费|
亚洲精品无码久久久久久久|
爱情岛论坛vip永久入口|
五十路在线视频|
91国产精品视频在线观看|
熟妇女人妻丰满少妇中文字幕|
久久精品免费网站|
波多野结衣视频播放|
免费在线观看日韩|
午夜黄色福利视频|
中文字幕日韩国产|
精品视频免费在线播放|
麻豆av免费看|
国产精品成人久久|
性做爰过程免费播放|
h片在线免费看|
午夜欧美福利视频|
伊人网在线视频观看|
亚洲欧美偷拍视频|
日本一本中文字幕|
无码人妻久久一区二区三区蜜桃|
欧美视频国产视频|
992在线观看|
99久久精品国产色欲|
国产一级特黄a大片免费|
永久免费成人代码|
国产又粗又猛又黄又爽|
国内自拍视频一区|
精品人体无码一区二区三区|
国产精品久久777777换脸|
亚洲乱码中文字幕久久孕妇黑人|
aaaaa一级片|
在线免费看av的网站|
欧美自拍小视频|
免费一级suv好看的国产网站|
av综合在线观看|
欧美色图亚洲天堂|
女人色极品影院|
性欧美丰满熟妇xxxx性久久久|
av片免费观看|
免费在线观看的毛片|
jizzjizzjizz国产|
亚洲精品人妻无码|
国产69精品久久久久久久久久|
欧美在线一区视频|
天天躁日日躁aaaa视频|
www.99视频|
久久国产视频播放|
欧美自拍小视频|
黄色高清视频网站|
亚洲一区二区三区无码久久|
国产精品爽爽久久|
亚洲一区 视频|
国产亚洲精品网站|
欧美黑人性猛交xxx|
四虎永久免费观看|
97超碰中文字幕|
久操视频免费在线观看|
日韩avxxx|
国产女人被狂躁到高潮小说|
黄色在线免费播放|
亚洲va欧美va|
中文字幕+乱码+中文乱码91|
欧美被狂躁喷白浆精品|
无码人妻一区二区三区精品视频|
91一区二区视频|
国产乱淫av片杨贵妃|
97人妻人人揉人人躁人人|
亚洲精品一区二区三区区别|
日韩 国产 欧美|
深爱五月综合网|
乱妇乱女熟妇熟女网站|
99热精品免费|
在线看片中文字幕|
午夜视频在线观看国产|
亚洲国产精品久久人人爱潘金莲|
婷婷激情五月综合|
久久黄色免费网站|
午夜免费看视频|
国产日产欧美视频|
久久久久久久久久网|
美国黄色片视频|
欧美 日韩 国产 成人 在线观看|
色诱av手机版|
日批视频免费播放|
亚洲av无码一区二区三区性色
|
波多野结衣久久久久|
欧美 日本 国产|
精品视频站长推荐|
久久无码专区国产精品s|
亚洲美女综合网|
国产www视频|
国产免费福利视频|
一本色道久久综合无码人妻|
亚洲大尺度在线观看|
www.国产com|
天堂中文字幕在线观看|
日韩特黄一级片|
国产精品111|
日韩av男人天堂|
黄色大片网站在线观看|
欧美三级午夜理伦|
色屁屁影院www国产高清麻豆|
日韩女同强女同hd|
国产免费观看av|
国产午夜精品久久久久|
无码人妻精品一区二区|
91黑人精品一区二区三区|
日本久久综合网|
羞羞色院91蜜桃|
亚洲图片中文字幕|
www.天堂在线|
四虎永久在线观看|
在线精品视频播放|
婷婷色一区二区三区|
亚洲色图27p|
youjizz.com亚洲|
欧美亚洲色图视频|
99re在线视频免费观看|
五月婷婷六月合|
久久久久免费看|
亚洲va在线观看|
国产又粗又大又爽|
少妇喷水在线观看|
中国黄色片视频|
国产又粗又黄又猛|
老司机午夜网站|
欧美日韩激情视频在线观看|
xxxx在线免费观看|
久久久久久久久久免费视频
|
亚洲涩涩在线观看|
精品肉丝脚一区二区三区|
中文字幕一区在线播放|
亚洲自拍偷拍另类|
伦伦影院午夜理论片|
欧美熟妇一区二区|
天天爱天天做天天操|
777久久久精品一区二区三区|
中文字幕第100页|
国产高潮久久久|
99久久免费国产精精品|
wwwxxx色|
日本黄色片免费观看|
久久国产精品视频在线观看|
在线观看av免费观看|
亚洲精品国产精品乱码视色|
色呦呦免费观看|
精品人妻一区二区三区蜜桃视频|
狠狠精品干练久久久无码中文字幕|
成人在线观看a|
91精品国产乱码久久久张津瑜|
国产精品无码在线播放|
第四色在线视频|
亚洲小视频在线播放|
一区二区xxx|
成人黄色免费网|
av免费观看不卡|
8x8x华人在线|
国产亚洲精品久久久久久无几年桃|
一区二区三区日|
精品人妻一区二区三区日产乱码卜|
国产高清精品软男同|
中文字幕 日韩 欧美|
一区二区日韩在线观看|
久久人人爽人人人人片|
www.亚洲成人网|
久久露脸国语精品国产91|
日本激情一区二区|
成年人午夜剧场|
欧美xxxx黑人xyx性爽|
亚洲精品中文字幕成人片
|
大又大又粗又硬又爽少妇毛片|
日韩不卡一二区|
国产精彩视频在线观看|
深爱五月激情五月|
亚洲第一页在线视频|
青青草手机在线视频|
老熟妇高潮一区二区高清视频|
女人裸体性做爰全过|
久久99爱视频|
亚洲第一大网站|
波多野结衣不卡视频|
操人视频免费看|
亚洲欧洲精品视频|
国产av熟女一区二区三区|
国产又黄又爽又色|
成年人在线观看av|
别急慢慢来1978如如2|
国产欧美久久久精品免费|
日本成人免费在线观看|
九九热视频免费|
亚洲欧美日韩综合在线|
国产av国片精品|
亚洲熟妇无码久久精品|
美女网站视频色|
免费网站看av|
久久久久亚洲AV成人无码国产|
91猫先生在线|
www.五月天激情|
av动漫在线免费观看|
久久青青草原亚洲av无码麻豆
|
超碰男人的天堂|
国产成人精品视频ⅴa片软件竹菊|
亚洲天堂手机在线|
性色av无码久久一区二区三区|
日韩欧美中文字幕一区二区|
aa片在线观看视频在线播放|
在线免费av播放|
色婷婷狠狠18禁久久|
久久精品午夜福利|
少妇精品高潮欲妇又嫩中文字幕|
国产主播自拍av|
aaa一区二区|
亚洲 自拍 另类小说综合图区|
国产精品一级视频|
日韩在线观看a|
av一区二区三|
老太脱裤子让老头玩xxxxx|
国产特级aaaaaa大片|
成人免费a级片|
国产成年妇视频|
国产精品裸体瑜伽视频|
午夜精品久久久久久久91蜜桃|
cao在线观看|
少妇高潮一区二区三区99小说|
欧美成人免费高清视频|
青青草精品在线|
污视频网址在线观看|
欧美图片一区二区|
一级免费在线观看|
黄色录像免费观看|
在线免费看av片|
成人一对一视频|
中国特级黄色片|
久久久久久久蜜桃|
国产麻豆视频在线观看|
一区二区三区免费在线|
免费看污视频的网站|
91视频 - 88av|
国产综合视频在线|
www.日本一区|
欧美熟妇激情一区二区三区|
国产成人一级片|
永久免费网站视频在线观看|
亚洲精品综合久久|
亚洲午夜精品一区|
国产午夜精品福利视频|
亚洲一级特黄毛片|
国产av无码专区亚洲精品|
喷水视频在线观看|
久久精品无码av|
免费看毛片的网址|
欧美激情 亚洲|
69成人免费视频|
你懂的av在线|
91av在线免费|
中国女人真人一级毛片|
成年人免费在线播放|
国产精品久久久免费观看|
无码人妻一区二区三区线|
www.玖玖玖|
久久久久久九九九九九|
国产又粗又猛又色又|
色片在线免费观看|
黄色一级片中国|
亚洲人成色777777精品音频|
天天操天天干视频|
青青艹视频在线|
特级西西www444人体聚色|
国产普通话bbwbbwbbw|
www.51色.com|
97在线免费视频观看|
jizz欧美性20|
国产成人精品无码高潮|
久久视频免费看|
人妻无码久久一区二区三区免费|
人人妻人人澡人人爽人人精品|
欧美成人精品网站|
最新天堂中文在线|
今天免费高清在线观看国语|
日本国产在线视频|
www.久久网|
日本美女久久久|
欧美爱爱视频免费看|
萌白酱视频在线|
亚洲AV无码久久精品国产一区|
国产又粗又猛又黄视频|
欧美成年人视频在线观看|
免费看污污视频|
精品无码一区二区三区|
黄色av小说在线观看|
无码人妻丰满熟妇精品区|
午夜视频在线网站|
av日韩一区二区三区|
一本一本久久a久久|
秘密基地免费观看完整版中文|
av网站免费播放|
无码人妻一区二区三区线|
日本免费观看网站|
青青在线视频免费观看|
久久久免费看片|
日本美女视频网站|
亚洲奶汁xxxx哺乳期|
这里只有久久精品视频|
日本一区二区免费在线观看|
我要看一级黄色大片|
a在线视频观看|
三上悠亚免费在线观看|
日韩一区二区三区四区视频|
性色av蜜臀av色欲av|
一起草最新网址|
国产香蕉在线观看|
国产三级漂亮女教师|
亚洲 小说区 图片区|
毛片在线免费视频|
国产精选第一页|
久久久久xxxx|
久久国产精品国产精品|
欧美视频免费播放|
2022亚洲天堂|
www国产精品内射老熟女|
男人添女人下部视频免费|
国产奶头好大揉着好爽视频|
永久免费看片直接|
影音先锋男人看片资源|
懂色av蜜桃av|
www.av天天|
毛片aaaaaa|
最新日韩免费视频|
国精产品视频一二二区|
天堂av网手机版|
快灬快灬一下爽蜜桃在线观看|
国产毛片久久久久久久|
亚洲精品视频大全|
九色porny自拍视频|
国产av自拍一区|
日韩一级片在线免费观看|
日本免费www|
国产3级在线观看|
男女性高潮免费网站|
天堂v在线视频|
亚洲啊啊啊啊啊|
9色porny|
国产无套内射久久久国产|
五月婷婷狠狠操|
在线a免费观看|
国产精品白浆一区二小说|
精品在线播放视频|
久久中文字幕免费|
影音先锋国产资源|
国产男女猛烈无遮挡|
好男人www在线视频|
国产老头和老头xxxx×|
国产视频久久久久久|
国产一区二区三区精品在线|
神马午夜精品91|
亚洲理论电影在线观看|
亚洲爆乳无码专区|
99中文字幕在线|
久草手机在线观看|
97精品人妻一区二区三区香蕉|
丰满大乳国产精品|
人妻 日韩 欧美 综合 制服|
四虎国产精品成人免费入口|
手机av在线看|
久久黄色片视频|
日本高清久久久|
好看的av在线|
99久久精品无免国产免费|
五月色婷婷综合|
国产在线观看h|
毛片在线视频观看|
高清一区二区视频|
97免费在线观看视频|
国产精品一级视频|
理论片大全免费理伦片|
欧美大片xxxx|
国产真实乱子伦|
日本五十路女优|
jizz中国少妇|
熟女丰满老熟女熟妇|
国产大尺度在线观看|
91淫黄看大片|
一级成人黄色片|
天堂在线视频网站|
免费看的黄色录像|
国产最新免费视频|
色播视频在线播放|
人妻中文字幕一区|
欧美肥妇bbwbbw|
免费黄色特级片|
久久久精品毛片|
日韩高清一二三区|