Django學習系列20 改進功能測試

2022-06-28 13:00:12 字數 3756 閱讀 4995

隱示等待和顯示等待

我們看看在功能測試中function_tests.py中的 time.sleep

inputbox.send_keys(keys.enter)

time.sleep(1)

self.check_for_row_in_list_table(

'1: buy peacock feathers

')

這就是所謂的「顯性等待」。這與「隱式等待」形成對比:在某些情況下,selenium會在認為頁面正在載入時嘗試「自動」等待您。

它甚至提供了乙個名為隱式等待的方法,讓您可以控制如果您向它請求乙個似乎還不在頁面上的元素,它將等待多長時間。

問題是,隱式等待總是有點不穩定,隨著selenium 3的發行,隱式等待變得更加不可靠。

同時,selenium團隊的普遍觀點是,隱性等待只是乙個壞主意,應該避免。

所以這個版本從一開始就有明確的顯示等待。但問題是那些時間誰說就是正確的時間呢?對於大多數測試,我們都是針對自己的機器來定,一秒鐘太長了,0.1秒就可以了。

但如果你把它定得這麼低,會因為膝上型電腦有點卡那就慢一點。

因此,讓我們用乙個工具來代替,這個工具將等待所需的時間,直到捕捉到任何故障的很長的超時時間。

我們將把check_for_row_in_list_table重新命名為wait_for_row_in_list_table,並為其新增一些輪詢/重試邏輯:

from selenium.common.exceptions import

webdriverexception

max_wait = 10 # 1【……】

defwait_for_row_in_list_table(self, row_text):

start_time =time.time()

while

true: # 2

try:

table = self.browser.find_element_by_id('

id_list_table

') # 3

rows = table.find_element_by_tag_name('tr'

) self.assertin(row_text, [row_text

for row in

rows])

return # 4

except

(assertionerror, webdriverexception) as e: # 5

if time.time() - start_time >max_wait: # 6

raise

e # 6

time.sleep(0.5) # 5

**解析:

1、max_wait」的常數來設定我們準備等待的最大時間。10秒應該足夠捕捉任何故障或隨機慢行。

2、這是乙個迴圈,除非我們到達兩條可能的出口路線之一。

3、下面是來自舊版本方法的三行斷言

4、 如果我們通過了它們,斷言通過了,我們就從函式返回並退出迴圈

5、但是,如果捕捉到異常,我們會等待很短的時間,然後迴圈重試。

6、這是我們的第二條逃生路線。如果我們達到這一點,這意味著我們的**每次嘗試都會引發異常,直到超過超時設定。所以這次,我們再次提出異常,讓它冒泡到我們的測試中,並且很可能在我們的回溯中結束,告訴我們為什麼測試失敗。

這段**讓我們難看清到底在做什麼?稍後,我們將重構乙個一般的wait_for helper,以將計時和重新提公升邏輯與測試斷言分離。

如果您以前使用過selenium,那麼您可能知道它有幾個helper函式要做等待。後面我們將構建兩個wait helper工具,這些工具可以生成漂亮、可讀的**。

現在我們可以重新命名我們的方法呼叫並刪除 time.sleeps:

#

頁面再次更新,清單中顯示了這兩個待辦事項

inputbox.send_keys(keys.enter)

time.sleep(1)

self.wait_for_row_in_list_table(

'1: buy peacock feathers')

#頁面中又顯示了乙個文字框,可以輸入其他的待辦事項

inputbox = self.browser.find_element_by_id('

id_new_item')

inputbox.send_keys(

'use peacock feathers to make a fly')

inputbox.send_keys(keys.enter)

time.sleep(1)

#頁面再次更新,她的清單中顯示了這兩個待辦事項

self.wait_for_row_in_list_table('

2: use peacock feathers to make a fly')

self.wait_for_row_in_list_table(

'1: buy peacock feathers

')

python manage.py test

ran 8 tests in

0.522s

failed (errors=1

)destroying test database

for alias '

default

'...

我們到了同乙個地方,注意到執行時間也縮短了幾秒鐘。現在看起來可能不多,但總而言之,為了檢查我們做得對,讓我們用幾種方法故意破壞測試,並看到一些錯誤。

def

wait_for_row_in_list_table(self, row_text):

start_time =time.time()

while true: #

2try

: table = self.browser.find_element_by_id('

id_list_table

') #

3 rows = table.find_element_by_tag_name('tr'

)

#self.assertin(row_text, [row_text for row in rows])

self.assertin('

foo', [row_text for row in

rows])

return#4

except (assertionerror, webdriverexception) as e: #

5if time.time() - start_time > max_wait: #

6raise e #

6 time.sleep(0.5) #

5

小結:不同的測試不應該互相影響。這意味著我們需要在每次測試結束時重置任何永久狀態。django的test runner通過建立乙個測試資料庫來幫助我們做到這一點,它在每個測試之間清除這個資料庫。

每當我們需要等待載入時,time.sleep()。但問題是,我們等待的時間總是有點太長,要麼太短,容易受到虛假失敗的影響,這會減慢我們的測試執行速度。

不依賴selenium的隱式等待理論上selenium確實做了一些「隱式」等待,但是實現在瀏覽器之間是不同的,並且在編寫時在selenium 3 firefox驅動程式中是非常不可靠的。「顯式優於隱式」,正如python的zen所說,所以更喜歡顯式等待。

Django學習系列之django分頁

from django.core.paginator import paginator objects post.objects.filter status published 從資料庫中取出所有status published狀態的文章p paginator objects,3 例項化pagina...

Django學習系列之CSRF

什麼是csrf 你的 會以為這個請求是使用者自己發來的,其實呢,這個請求是那個惡意 偽造的 django提供的csrf防護機制 django 第一次響應來自某個客戶端的請求時,會在伺服器端隨機生成乙個 token,把這個 token 放在 cookie 裡。然後每次 post 請求都會帶上這個 to...

Django2 0學習筆記(一)

基於python的一款有截止日期,給完美主義者使用的web框架。優點 開發速度快 令人放心的安全 可拓展性強。注意 python和django版本的對應。這裡用的是python3.6和django2.0。1 在桌面建乙個資料夾 test 在命令列輸入 django admin startprojec...