W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
你需要一遍一遍地在你的游戲中輸入命令,來測試游戲的功能是否正常。這個(gè)過程是很枯燥無味的。如果能寫一小段代碼用來測試你的代碼豈不是更好?然后無論你對程序做了什么修改,或者添加了什么新東西,你只要“跑一下你的測試”,而這些測試能確認(rèn)程序依然能正確運(yùn)行。這些自動(dòng)測試不會(huì)抓到所有的 bug,但可以讓你無需重復(fù)輸入命令運(yùn)行你的代碼,從而為你節(jié)約很多時(shí)間。
從這節(jié)練習(xí)開始,以后的練習(xí)將不會(huì)有“你應(yīng)該看到的結(jié)果”部分,取而代之的是一個(gè)“你應(yīng)該測試的東西”。從現(xiàn)在開始,你需要為自己寫的所有代碼寫自動(dòng)化測試,而這將讓你成為一個(gè)更好的程序員。
我不會(huì)解釋你為什么需要寫自動(dòng)化測試。我要告訴你的是,你想要成為一個(gè)程序員,而程序的作用是讓無聊冗繁的工作自動(dòng)化,測試一個(gè)軟件毫無疑問是無聊冗繁的,所以你還是寫點(diǎn)代碼讓它為你測試的更好。
這應(yīng)該是你需要的所有的解釋了。因?yàn)槟銓憜卧獪y試的原因是讓你的大腦更加強(qiáng)健。讀了這本書,你寫了很多代碼讓它們實(shí)現(xiàn)一些事情。現(xiàn)在你將更進(jìn)一步,寫出懂得你寫的其他代碼的代碼。這個(gè)寫代碼測試你寫的其他代碼的過程將強(qiáng)迫你清楚的理解你之前寫的代碼。這會(huì)讓你更清晰地了解你寫的代碼實(shí)現(xiàn)的功能及其原理,而且讓你對細(xì)節(jié)的注意更上一個(gè)臺階。
我們將拿一段非常簡單的代碼為例,寫一個(gè)簡單的測試,這個(gè)測試將建立在上節(jié)我們創(chuàng)建的項(xiàng)目骨架上面。
首先從你的項(xiàng)目骨架創(chuàng)建一個(gè)叫做ex47
的項(xiàng)目。下面是你要采取的步驟。我會(huì)給出文字說明,而不是直接告訴你該如何寫代碼,所以你要自己弄明白并寫出代碼。
- 復(fù)制
skeleton
到ex47
- 將所有的
NAME
重命名為ex47
- 修改所有文件中
NAME
為ex47
- 最后刪除所有的
*.pyc
文件
如果遇到什么困難,回顧一下練習(xí)46,如果你不能簡單的完成這些,那你需要多練習(xí)幾次。
NOTE:記得通過命令
nosetests
來檢測你的測試代碼沒有錯(cuò)誤信息。你可以通過python ex47_tests.py
來運(yùn)行,但是它不會(huì)那么容易的運(yùn)行,你必須保證你的每一個(gè)測試文件正常運(yùn)行。
接下來創(chuàng)建一個(gè)簡單的ex47/game.py
文件,里邊放一些用來被測試的代碼。我們現(xiàn)在放一個(gè)傻乎乎的小 class 進(jìn)去,用來作為我們的測試對象:
class Room(object):
def __init__(self, name, description):
self.name = name
self.description = description
self.paths = {}
def go(self, direction):
return self.paths.get(direction, None)
def add_paths(self, paths):
self.paths.update(paths)
準(zhǔn)備好了這個(gè)文件,接下來把測試骨架改成這樣子:
from nose.tools import *
from ex47.game import Room
def test_room():
gold = Room("GoldRoom",
"""This room has gold in it you can grab. There's a
door to the north.""")
assert_equal(gold.name, "GoldRoom")
assert_equal(gold.paths, {})
def test_room_paths():
center = Room("Center", "Test room in the center.")
north = Room("North", "Test room in the north.")
south = Room("South", "Test room in the south.")
center.add_paths({'north': north, 'south': south})
assert_equal(center.go('north'), north)
assert_equal(center.go('south'), south)
def test_map():
start = Room("Start", "You can go west and down a hole.")
west = Room("Trees", "There are trees here, you can go east.")
down = Room("Dungeon", "It's dark down here, you can go up.")
start.add_paths({'west': west, 'down': down})
west.add_paths({'east': start})
down.add_paths({'up': start})
assert_equal(start.go('west'), west)
assert_equal(start.go('west').go('east'), start)
assert_equal(start.go('down').go('up'), start)
這個(gè)文件導(dǎo)入了你在ex47.game
創(chuàng)建的Room
這個(gè)類,接下來我們要做的就是測試它。于是我們看到一系列的以test_
開頭的測試函數(shù),它們就是所謂的“測試用例(test case)”,每一個(gè)測試用例里面都有一小段代碼,它們會(huì)創(chuàng)建一個(gè)或者一些房間,然后去確認(rèn)房間的功能和你期望的是否一樣。它測試了基本的房間功能,然后測試了路徑,最后測試了整個(gè)地圖。
這里最重要的函數(shù)是assert_equal
,它保證了你設(shè)置的變量,以及你在Room
里設(shè)置的路徑和你的期望相符。如果你得到錯(cuò)誤的結(jié)果的話,nosetests
將會(huì)打印出一個(gè)錯(cuò)誤信息,這樣你就可以找到出錯(cuò)的地方并且修正過來。
在寫測試代碼時(shí),你可以照著下面這些不是很嚴(yán)格的指南來做:
- 測試腳本要放到
tests/
目錄下,并且命名為BLAH_tests.py
,否則nosetests
就不會(huì)執(zhí)行你的測試腳本了。這樣做還有一個(gè)好處就是防止測試代碼和別的代碼互相混掉。- 為你的每一個(gè)模組寫一個(gè)測試。
- 測試用例(函數(shù))保持簡短,但如果看上去不怎么整潔也沒關(guān)系,測試用例一般都有點(diǎn)亂。
- 就算測試用例有些亂,也要試著讓他們保持整潔,把里邊重復(fù)的代碼刪掉。創(chuàng)建一些輔助函數(shù)來避免重復(fù)的代碼。當(dāng)你下次在改完代碼需要改測試的時(shí)候,你會(huì)感謝我這一條建議的。重復(fù)的代碼會(huì)讓修改測試變得很難操作。
- 最后一條是別太把測試當(dāng)做一回事。有時(shí)候,更好的方法是把代碼和測試全部刪掉,然后重新設(shè)計(jì)代碼。
$ nosetests
...
----------------------------------------------------------------------
Ran 3 tests in 0.008s
OK
如果一切工作正常的話,你看到的結(jié)果應(yīng)該就是這樣。試著把代碼改錯(cuò)幾個(gè)地方,然后看錯(cuò)誤信息會(huì)是什么,再把代碼改正確。
- 仔細(xì)讀讀
nosetest
相關(guān)的文檔,再去了解一下其他的替代方案。- 了解一下 Python 的 “doc tests” ,看看你是不是更喜歡這種測試方式。
- 改進(jìn)你游戲里的 Room,然后用它重建你的游戲,這次重寫,你需要一邊寫代碼,一邊把單元測試寫出來。
nosetest
的時(shí)候,我遇到一個(gè)語法錯(cuò)誤如果你遇到這個(gè)報(bào)錯(cuò),看看錯(cuò)誤信息是怎么說的,并改正該行或上一行的錯(cuò)誤。類似
nosetest
的工具是在運(yùn)行你的代碼和測試代碼,所以他可以像運(yùn)行python一樣發(fā)現(xiàn)你的語法錯(cuò)誤。
ex47.game
確認(rèn)你創(chuàng)建了
ex47/__init__.py
文件,參照練習(xí)46,看它是如何做的。如果這個(gè)文件沒有問題,在OSX/Linux下執(zhí)行:export PYTHONPATH=.
在window下執(zhí)行$env:PYTHONPATH = "$env:PYTHONPATH;."
,最后,確認(rèn)你是用nosetest
運(yùn)行測試腳本,而不是用python。
nosetest
的時(shí)候,遇到一個(gè)報(bào)錯(cuò)UserWarning
你可能安裝了兩個(gè)版本的python或者沒有使用
distribute
,按照我在練習(xí)46中所描述的安裝distribute
或pip
。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: