1. 程式人生 > 實用技巧 >Python+Selenium框架設計篇之6-進一步實現POM和可能遇到問題解決辦法

Python+Selenium框架設計篇之6-進一步實現POM和可能遇到問題解決辦法

本文進一步演示POM的具體實現,前面POM只是一個頁面,一個測試指令碼,現在我們要實現三個頁面,兩個測試指令碼。在pageobjects包下,我新建了2個頁面物件:百度新聞首頁,百度體育新聞首頁,具體檔案結構如下圖,其他和之前專案層級結構保持不變。

百度首頁頁面類程式碼(baidu_homepage.py),定義了百度新聞的入口

# coding=utf-8
 
from framework.base_page import BasePage
 
 
 
 
 
class HomePage(BasePage):
 
input_box = "id=>kw"
 
search_submit_btn 
= "xpath=>//*[@id='su']" # 百度新聞入口 news_link = "xpath=>//*[@id='u1']/a[@name='tj_trnews']" def type_search(self, text): self.type(self.input_box, text) def send_submit_btn(self): self.click(self.search_submit_btn) def click_news(self): self.click(self.news_link) self.sleep(
2)

百度新聞首頁的頁面類程式碼(baidu_news_home.py),定義了體育新聞入口

# coding=utf-8
 
from framework.base_page import BasePage
 
 
 
 
 
class NewsHomePage(BasePage):
 
# 點選體育新聞入口
 
sports_link = "xpath=>//*[@id='channel-all']/div/ul/li[5]/a"
 
 
 
def click_sports(self):
 
self.click(self.sports_link)
 
self.sleep(2)

百度體育新聞頁面類程式碼(news_sports_home.py)

# coding=utf-8
 
from framework.base_page import BasePage
 
 
 
 
 
class SportNewsHomePage(BasePage):
 
# NBA入口
 
nba_link = "xpath=>//*[@id='channel-submenu']/div/span[2]/a[1]"
 
 
 
def click_nba_link(self):
 
self.click(self.nba_link)
 
self.sleep(2)
測試類程式碼(test_nba_news_view.py)

測試步驟大概是:百度首頁點選新聞連結-進入新聞主頁,點選體育-進入體育新聞主頁,點選NBA-進入NBA頁面-其他後續指令碼操作。為什麼要採用這樣的步驟呢,幹嘛不直接driver.get('nba的連結')?因為我們就是要利用POM的思想去寫我們測試指令碼,才有上面的測試步驟。

# coding=utf-8
 
import time
 
import unittest
 
from framework.browser_engine import BrowserEngine
 
from pageobjects.baidu_homepage import HomePage
 
from pageobjects.baidu_news_home import NewsHomePage
 
from pageobjects.news_sport_home import SportNewsHomePage
 
 
 
 
 
class ViewNBANews(unittest.TestCase):
 
def setUp(self):
 
browse = BrowserEngine(self)
 
self.driver = browse.open_browser(self)
 
 
 
def tearDown(self):
 
self.driver.quit()
 
 
 
def test_view_nba_views(self):
 
# 初始化百度首頁,並點選新聞連結
 
baiduhome = HomePage(self.driver)
 
baiduhome.click_news()
 
# 初始化一個百度新聞主頁物件,點選體育
 
newshome = NewsHomePage(self.driver)
 
newshome.click_sports()
 
#初始化一個體育新聞主頁,點選NBA
 
sportnewhome = SportNewsHomePage(self.driver)
 
sportnewhome.click_nba_link()
 
sportnewhome.get_windows_img()
 
 
 
if __name__ == '__main__':
 
unittest.main()

通過上面的

指令碼,進入一個新的頁面,就要初始化這個頁面的物件,然後才能呼叫這個頁面相關的方法,driver這個例項物件在不同頁面之間切換,這個就是POM的核心內容。我們來測試執行這個類看看,結果報錯。

StaleElementReferenceException: Message: stale element reference: element is not attached to the page document

原因分析:

字面意思是說,頁面元素不在當前頁面物件沒有載入到頁面,就不能找到元素,不能進行點選,這個報錯發生在,百度新聞首頁點選體育這行程式碼裡。

由於我們的driver這個例項物件在不同的頁面裡切換,可能造成了這個報錯,這個問題在python+selenium遇到過,java+selenium沒有遇到,國外網站,有人建議,既然找不到這個元素,那麼在腳本里,就直接driver.find_elemen(xpath)再找一次。也就是說,可能我們利用頁面物件方法,點選不了這個體育連結,那麼我們直接在腳本里通過find_element方法去定位體育這個元素,然後再點選。這個也算是一個bug,目前暫時沒有更好辦法解決,不知道以後chromedriver.exe升級會不會解決這個問題不好說。

我們調整下我們測試類程式碼,新增find_element()語句

# coding=utf-8
 
import time
 
import unittest
 
from framework.browser_engine import BrowserEngine
 
from pageobjects.baidu_homepage import HomePage
 
from pageobjects.baidu_news_home import NewsHomePage
 
from pageobjects.news_sport_home import SportNewsHomePage
 
 
 
 
 
class ViewNBANews(unittest.TestCase):
 
def setUp(self):
 
browse = BrowserEngine(self)
 
self.driver = browse.open_browser(self)
 
 
 
def tearDown(self):
 
self.driver.quit()
 
 
 
def test_view_nba_views(self):
 
# 初始化百度首頁,並點選新聞連結
 
baiduhome = HomePage(self.driver)
 
#baiduhome.click_news()
 
self.driver.find_element_by_xpath("//*[@id='u1']/a[@name='tj_trnews']").click()
 
# 初始化一個百度新聞主頁物件,點選體育
 
newshome = NewsHomePage(self.driver)
 
#self.driver.refresh()
 
#newshome.click_sports()
 
self.driver.find_element_by_xpath("//*[@id='channel-all']/div/ul/li[5]/a").click()
 
#初始化一個體育新聞主頁,點選NBA
 
sportnewhome = SportNewsHomePage(self.driver)
 
#sportnewhome.click_nba_link()
 
self.driver.find_element_by_xpath("//*[@id='channel-submenu']/div/span[2]/a[1]").click()
 
sportnewhome.get_windows_img()
 
 
 
if __name__ == '__main__':
 
unittest.main()

其實,我們之前頁面物件呼叫點選相關元素進入下一個頁面,在回放指令碼是看起作用了,但是就是報錯,所以這裡,只好在三個地方點選進入下一個頁面的時候,採用self.driver.find_element()方法。這個和我們POM的思想,頁面物件只寫元素定位和相關方法,指令碼類一般不寫頁面元素定位相矛盾,是吧。也許未來能解決這個問題,或者你接受當前這個方法,或者,你單獨寫一個進入到NBA的類,例如直接driver.get()然後封裝靜態類,當做其他NBA頁面指令碼的測試韌體引入,這樣也可以。

實際專案指令碼開發也應該有一些公共方法封裝成模組或者靜態類,例如,把登入事件寫成靜態類,第二個用例是收藏一篇文章,收藏的測試前提就是登入,所以在收藏類的測試韌體中的setUp()裡就呼叫登入的模組指令碼。同樣,你寫登入的事件,可能封裝了瀏覽器的呼叫。具體問題要具體分析,實際指令碼開發過程要隨機應變,一種方法實現起來困難,就想辦法繞過去,這個是自動化測試工程師要一直面臨的挑戰。

最後

小楓希望的是給大家幫助,在這裡也希望大家共同進步,

如果對測試框架感興趣小楓這推薦一個群,裡面自動化測試,面試寶典,測試框架等等,進群免費領取喲,1140267353

掃碼進群更多驚喜,歡迎加入這個大家庭!!!!