原來(lái)雖然是索引超出范圍,但是泛型集合拋的卻是ArgumentOutOfRangeException;鹦橇,MS為什么不和數(shù)組一樣拋IndexOutOfRangeException異常呢?其實(shí)List中的元素也是存儲(chǔ)在數(shù)組中的,我想MS是畫(huà)蛇添足了。把catch語(yǔ)句改下異常類(lèi)型,測(cè)試通過(guò)了,其他和預(yù)想的都一樣。
第一個(gè)測(cè)試方法完成了。寫(xiě)測(cè)試看來(lái)還是有點(diǎn)麻煩,NUnit的工作只是將你測(cè)試類(lèi)里的方法一起運(yùn)行并顯示結(jié)果。但測(cè)試用例和邏輯,都得自己寫(xiě),只是參數(shù)驗(yàn)證還好說(shuō)。下面要驗(yàn)證正常輸出結(jié)果的隨機(jī)性,費(fèi)了點(diǎn)功夫。
正常輸出,應(yīng)該驗(yàn)證這些:個(gè)數(shù)、范圍、元素不重復(fù)、運(yùn)行不重復(fù)、隨機(jī)分布。
第二個(gè)測(cè)試方法只比較了一下兩次運(yùn)行不重復(fù),這里不把這個(gè)小算法抽象成機(jī)關(guān)重重的黑盒了,那應(yīng)該測(cè)試個(gè)幾百幾千次,甚至更多,看結(jié)果的重復(fù)率。還有怎么高效地比較N個(gè)集合中,每個(gè)集合都很長(zhǎng)很長(zhǎng),是否有元素完全相同的呢,我想可以對(duì)集合生成一個(gè)MD5簽名再比較。
驗(yàn)證隨機(jī)寫(xiě)在第三個(gè)驗(yàn)證方法里,和驗(yàn)證結(jié)果元素個(gè)數(shù)和范圍在一起。關(guān)鍵來(lái)了,自己覺(jué)得它是隨機(jī)的不行,怎么判斷這些數(shù)是隨機(jī)的?憑什么標(biāo)準(zhǔn)判斷呢?要把判斷的依據(jù)用編程語(yǔ)言告訴計(jì)算機(jī)。
隨機(jī)數(shù)有什么特征,我思索著,終于總結(jié)出:隨機(jī)是不均勻又均勻。一個(gè)隨機(jī)數(shù),可以是在指定范圍內(nèi)任意值,此謂不均勻。但一次生成的一組隨機(jī)數(shù)總體來(lái)看,若把總范圍分成若干跨度相同的子范圍,每個(gè)子范圍內(nèi)應(yīng)有差不多數(shù)量的隨機(jī)數(shù)。隨機(jī)數(shù)總數(shù)越多,在各范圍內(nèi)分布的比例越接近,此謂均勻。說(shuō)到分布,想起來(lái)了,我們中學(xué)學(xué)過(guò)一個(gè)描述分布的數(shù)學(xué)概念:方差。我們生成的隨機(jī)數(shù),應(yīng)對(duì)范圍的中間值有一定的方差。而這個(gè)方差,應(yīng)該接近于均勻分布情況下的方差。我估計(jì)平均每次浮動(dòng)在10%內(nèi),如果通不過(guò),再調(diào)整一下。
這里采用循環(huán)生成測(cè)試參數(shù),以后應(yīng)該會(huì)經(jīng)常用到這種方式。寫(xiě)完,生成項(xiàng)目,NUnit加載,Run,大紅條!看來(lái)浮動(dòng)范圍限制得太小,但是一看NUnit Text OutPut欄,發(fā)現(xiàn)有的結(jié)果浮動(dòng)值過(guò)于懸殊,達(dá)數(shù)倍之多。結(jié)果之間差別也很大,不對(duì)勁!
在項(xiàng)目里調(diào)試,一下子發(fā)現(xiàn),不,應(yīng)該說(shuō)是想起來(lái):生成隨機(jī)數(shù)的種子應(yīng)該在循環(huán)外初始化。不然,生成的全是連續(xù)的“隨機(jī)數(shù)”。
做修改,NUnit重新Run一下,通過(guò)!這才是真正的隨機(jī)數(shù),隨機(jī)得很暴力,平均方差浮動(dòng)不到1%!
單元測(cè)試也是程序開(kāi)發(fā)的一部分,希望與大家一起學(xué)習(xí)交流,成為軟件開(kāi)發(fā)的現(xiàn)代化正規(guī)軍。