1. 程式人生 > >Selenium自動化測試入門(基於Python)

Selenium自動化測試入門(基於Python)

本人小白 最近在嘗試學習Python 開篇記錄 只為交流 相互學習O(∩_∩)O~~

Selenium,化學元素硒的英文示意,對於軟體測試來書,則是一個主要用於Web應用程式自動化測試的工具集合;

之前有這個計劃來學習和使用自動化測試到專案中去,以滿足公司需求,所以閒時就買了本書,內容較簡潔,實踐學習中;

前言:

旨在學習使用Python語言呼叫Selenium WebDriver介面進行自動化測試;

作為一名小白,我們先來看看所需的入門知識和資訊;

1.Selenium WebDriver:業界通用的測試框架,不僅是web測試的標準,同時在移動測試領域也是底層的核心驅動框架;

2.Python作為動態語言,其優點多多,前一階段用了一段時間簡單熟悉了下

Python語法,感興趣的同學可移步檢視;

Selenium包括一系列的工具元件:

1.Selenium IDE:是嵌入到FireFox瀏覽器的外掛,用於在Firefox上錄製和回放Selenium指令碼;

雖然只能在Firefox下使用,但它能將錄製好的指令碼轉換成各種Selenium WebDriver支援的程式語言,進而擴充套件到更廣泛的瀏覽器型別;

2.Selenium WebDriver:可支援多種語言,用於操作瀏覽器的一套API;支援各型別瀏覽器,跨作業系統;

WebDriver為諸多語言提供完備的,用於實現web自動化測試的第三方庫;

3.Selenium Standalone Server:包括Selenium Grid、遠端控制、分散式部署等,均可實現Selenium指令碼的高效執行與拓展;

利用Grid使得自動化測試可以並行執行,甚至在跨平臺、異構的環境中執行,包括主流的移動端環境,如Android、iOS;

學習準備:Python語言及語法,Web前段知識(這個瞭解的很少/(ㄒoㄒ)/~~),至於一些前期準備和環境配置,我們稍後來實踐;

一、基於Python的Selenium WebDriver入門

Selenium可以自動操縱瀏覽器來做很多,如模擬與瀏覽器的互動,而且支援到多數主流瀏覽器;

我們首先需要選擇一門語言來編寫自動化指令碼,而這門語言需要有Selenium client library支援;我們選擇Python;

1.1 安裝Python和Selenium包

之後執行終端命令:pip3 install -U selenium 

1.2 PyCharm設定

PyCharm有兩個版本:社群版和專業版,社群版是免費的,可以下載使用;

在使用PyCharm時,需要配置Python的直譯器,我們選擇支援selenium的Python版本直譯器;

1.3 Selenium WebDriver基於Python的例項指令碼

我們嘗試建立一個引用Selenium WebDriver Client library的Python指令碼,使用Selenium WebDriver提供的類和方法模擬使用者與瀏覽器的互動;

我們嘗試使用百度搜索來實踐這個指令碼:搜尋“銅錢貫”,並列印搜尋記錄的內容:

Python指令碼編輯如下:(searchproducts.py)

# -*- coding:utf-8 -*-

from selenium import webdriver

# create a new Firefox session

driver = webdriver.Firefox()
driver.implicitly_wait(10)#設定超時時間
driver.maximize_window()#視窗最大化顯示

#  navigate to the application home page

driver.get("http://www.baidu.com/")

# get the search textbox

search_field = driver.find_element_by_id("kw")#找到輸入框
search_field.clear()#清空當前輸入內容

# enter search keyword and submit

search_field.send_keys("銅錢貫")#重新這是搜尋關鍵字
search_field.submit()#提交進行搜尋

# get all the anchor elements which have product names displayed
#  currently on result page using find_ elements_ by_ xpath method

products = driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

# get the number of anchor elements found

print ("Found " + str(len(products)) + "products:")

# iterate through each anchor element and print the text that is
#  name of the product

for product in products:
    print (product.text)

#  close the browser window

# driver.quit()

接下來我們執行指令碼:

這裡可能會遇到這樣一個錯誤:

下載符合系統的檔案,解壓之後進行移動:

值得說明的是geckodriver是針對Firefox的,和我們一會要說的ChromeDriver和InternetExplorerDriver類似;

問題解決了我們繼續;

我們會看到一個Firefox瀏覽器視窗訪問百度搜索頁,同時進行關鍵字的搜尋,順利的話,最終會在控制檯列印輸出上圖中標籤標記的記錄內容;(部分輸出內容如下)

Found 13products:
- 銅錢貫 註冊資本1.2億元人民幣 - 環嘉集團 銅錢貫 出借專區 安全保障 幫助中心 新手攻略 銅錢貫董事長於東昇:發展網際網路金融一定要回歸實體經濟>> 春田花花...
銅錢貫精選優質標的,企貸寶、房貸寶、車貸寶產品由借款人、擔保人提供抵押、質押擔保,有效降低風險,提高投資...
2018年3月30日 - 銅錢貫網貸平臺檔案是由網貸之家為您精心收集整理的銅錢貫網貸平臺有關的資訊和資料,供您在投資理財時參考使用
“銅錢貫”是傑銘升資訊科技(北京)有限公司針對廣大使用者傾力打造的一款安全、高效、專業的網際網路金融綜合資訊服務平臺。銅錢貫以國務院印發的《推進普惠...
2018年5月21日 - 【編者按】作為與您投資息息相關的三方資訊平臺,網貸之家為你提供銅錢貫的每天運營資料報告,關於銅錢貫怎麼樣、銅錢貫好不好等之類的投資疑問,以下的...

語句的分析示意,簡單作了註釋,還有很多功能需要不斷的去學習和使用;

1)從Selenium包匯入WebDriver才能使用Selenium WebDriver的方法;

2)選用一個瀏覽器驅動例項,會提供一個幾口去呼叫Selenium命令來跟瀏覽器互動;

3)設定30s隱式等待時間來定義Selenium執行步驟的超時時間;

4)呼叫driver.get()方法訪問該應用程式,方法呼叫後,WebDriver會等待,一直到頁面載入完成才繼續執行指令碼;

5)Selenium WebDriver提供多種方法來定位和操作這些元素,例如設定值,單擊按鈕,在下拉元件中選擇選項等;這裡使用find_element_by_id來定位搜尋輸入框;這個方法會返回第一個id屬性值與輸入引數匹配的元素;(HTML元素是用標籤和屬性定義的)

6)通過send_keys()方法輸入新的特定值,呼叫submit()提交搜尋請求;

7)載入搜尋結果頁面,我們讀取結果列表的內容並列印輸出;通過find_elements_by_xpath獲取路徑滿足class='c-abstract'的所有div標籤,它將返回多於一個的元素列表;

8)最後我們列印,獲取到的標籤的文字內容;在指令碼的最後,我們可以使用driver.quit()來關閉瀏覽器;

這個例子向我們展示瞭如何使用Selenium WebDriver和Python配合來建立一個簡單的自動化指令碼;(眼下這個指令碼還沒有測試什麼)

Selenium.webdriver模組實現了Selenium所支援的各種瀏覽器驅動程式,包括Firefox、Chrome、IE、Safari等;

此外,RemoteWebDriver則是用於遠端機器進行瀏覽器測試的;

對於IE瀏覽器:

需要下載並安裝InternetExplorerDriver,是一個獨立的服務,他實現了WebDriver的協議,使得WebDriver可以可以和IE瀏覽器互動;

下載解壓放到儲存指令碼的目錄中即可;(IE7以上版本,每個區域的保護模式需要設定相同的值)

IE下的指令碼需要我們修改才能使用;

對於Chrome瀏覽器:

需要下載ChromeDriver服務,該服務支援多系統,有Chromium team開發維護;

下載完成後複製到指令碼的目錄中;

修改指令碼使其支援Chrome瀏覽器;

修改指令碼的方式這是通過os模組,通過os.path.dirname(__file__) + "\chromedriver"得到的執行檔案路徑,作為webdriver.Chrome(xxx)啟動驅動器例項的引數,IE亦如此;(Windows下需要加上可執行檔案的字尾,如.exe)

接下來,我們嘗試通過Selenium WebDriver使用unittest庫來建立自動化單元測試,並學習如何建立並執行一組測試指令碼;

二、使用unittest編寫單元測試

首先我們來回顧一下Selenium WebDriver,它是一個瀏覽器自動化測試的API集合;提供了很多與瀏覽器互動的特性;

但是,僅僅使用Selenium WebDriver,我們還有一些無法實現的:比如 實現執行測試前置條件、測試後置條件,比對預期結果和實際結果,檢查程式的狀態,生成測試報告,建立資料驅動測試等功能;

那麼,現在我們來看如何使用unittest來建立基於Python的Selenium WebDriver測試指令碼;

2.1 什麼是unittest

unittest單元測試框架:

一般也稱為PyUnit,是從Java程式開發中廣泛應用的JUnit啟發而來的;我們可以使用unittest為任何專案建立全面的測試套件;

unittest使我們具備建立測試用例、測試套件、測試夾具的能力;

unittest元件:

1)Test Fixture(測試夾具):

使用測試夾具,可以定義在單個或多個測試執行之前的準備工作和測試執行之後的清理工作;

2)Test Case(測試用例):

unittest中執行測試的最小單元,通過驗證unittest提供的assert方法來驗證一組特定的操作和輸入以後得到的響應;

unittest提供了一個名為TestCase的基礎類,可以用來建立測試用例;

3)Test Suit(測試套件):

一個測試套件是多個測試或測試用例的集合,是針對被測程式的對應的功能和模組建立的一組測試,一個測試套件內的測試用例將一起執行;

4)Test Runner(測試執行器):

測試執行器負責測試執行排程並且生成測試結果給使用者;

測試執行器可以使用圖形介面、文字介面或者特定的返回值來展示測試執行結果;

5)Test Report(測試報告):

測試報告展示所有執行用例的成功或者失敗狀態的彙總;包括失敗的測試步驟的預期結果和實際結果,還有整體執行狀況和執行時間的彙總;

2.2 使用unittest來寫Selenium WebDriver測試

一般的測試可被拆分為3部分,即3A`s:

1)Arrange:初始化前置條件,初始化被測試的物件,相關配置和依賴;

2)Act:執行功能操作;

3)Assert:用來校驗實際結果與預期結果是否一致;

這是一種方法,我們接下來將應用此方法來為unittest建立測試;

2.3 用TestCase類來實現一個測試

我們將通過整合TestCase類並且 在測試類中為每一個測試新增測試方法來建立單個測試或者一組測試;

TestCase中的assert方法,最主要的任務是 呼叫assertEqual()來校驗結果;assertTrue()來驗證條件;assertRaises來驗證預期的異常;

除了新增測試,還可以新增測試夾具,setUp()方法和tearDown()方法;

一個測試用例是從setUp()方法開始執行,因此可以在每個測試開始前執行一些初始化的任務;此方法無引數,也無返回值;

接著編寫test方法,這些測試方法命名為test開頭,這種命名約定通知test runner哪個方法代表測試方法;

值得注意的是:test runner能找到的每個測試方法,都會在執行測試方法之前先執行setUp()方法,這樣有助於確保每個測試方法都能夠依賴於相同的環境;

tearDown()方法會在測試執行完成之後呼叫,用來清理所有的初始值;

最後就是執行測試:為了能通過命令列測試,我們可以在測試中新增對main方法的呼叫;我們將傳遞verbosity引數以便使詳細的測試結果展示在控制檯;

測試程式碼如下:

# -*- coding:utf-8 -*-

import unittest
from selenium import webdriver

class SearchTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(15)
        self.driver.maximize_window()

        self.driver.get('http://www.baidu.com')

    def test_search_by_category(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')
        self.search_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        self.assertEqual(10, len(products))

    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

如果測試通過則,瀏覽器最後會退出,如果出錯的話,控制檯則會打印出相關資訊:

通過終端命令列執行的結果如下:

修改預期值,測試報錯:

上一個例項,我們添加了一個測試,我們還可以用一組測試來構建一個測試類;這樣有助於為一個特定功能建立一組更合乎邏輯的測試;

新的測試方法命名同樣要以test開頭;簡單測試我們複製第一個示例中的測試,修改測試方法名;通過終端再次執行:(searchtest.py)

# -*- coding:utf-8 -*-

import unittest
from selenium import webdriver

class SearchTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(15)
        self.driver.maximize_window()

        self.driver.get('http://www.baidu.com')

    def test_search_by_category(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')
        self.search_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        self.assertEqual(11, len(products))

    def test_search_by_category1(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')
        self.search_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        self.assertEqual(10, len(products))

    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

執行結果如下:

同時我們看到這這樣的一個效果:兩個Firefox的例項開啟和關閉,對應setUp()和tearDown()方法執行的結果;

為了能讓各個測試方法共用一個Firefox例項,我們可以建立類級別的setUp()和tearDown()方法:

1)通過setUpClass()方法和tearDownClass()方法及@classmethod標識來實現;

2)這兩個方法使在類級別初始化資料,替代了方法級別的初始化;

我們修改測試指令碼,並重新執行:(searchtest1.py)

# -*- coding:utf-8 -*-

import unittest
from selenium import webdriver

class SearchTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()
        cls.driver.implicitly_wait(15)
        cls.driver.maximize_window()

        cls.driver.get('http://www.baidu.com')

    def test_search_by_category(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')
        self.search_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        self.assertEqual(11, len(products))

    def test_search_by_category1(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')
        self.search_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        self.assertEqual(10, len(products))

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

2.4 學習unittest提供的不同型別的assert方法

斷言:unittest的TestCase類提供了很多實用的方法來校驗預期結果和實際結果是否一致;

assertEqual(a, b [, msg]); assertNotEqual(a, b [, msg]);

assertTrue(x [, msg]); assertFalse(x [, msg]);

assertIsNot(a, b [, msg]);

assertRaises(exc, fun, *args, **kwds);

......

2.5 為一組測試建立TestSuite

應用unittest的TestSuites特性,可以將不同的測試組成一個邏輯組,然後設定統一的測試套件,並通過一個命令來執行;

具體通過TestSuites、TestLoader和TestRunner類來實現的;

我們將上一個指令碼命名為searchtest1.py,同時我們新建一個指令碼searchtest2.py如下:(searchtest2.py)

# -*- coding:utf-8 -*-

import unittest
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By

class SearchTestHomePage(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()
        cls.driver.implicitly_wait(15)
        cls.driver.maximize_window()

        cls.driver.get('http://www.baidu.com')

    def test_search_by_category(self):
        self.assertTrue(self.is_element_present(By.ID, "kw"))

    def test_search_by_category1(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')
        self.search_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        self.assertEqual(10, len(products))

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def is_element_present(self, how, what):
        """"""
        try:
            self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e:
            return False
        return True

if __name__ == '__main__':
    unittest.main(verbosity=2)

接下來,我們來看看TestSuites特性是如何工作的:

新建另一個指令碼如下:(searchtestsuites.py)

# -*- coding:utf-8 -*-

import unittest
from searchtest1 import SearchTest
from searchtest2 import SearchTestHomePage

search_test = unittest.TestLoader().loadTestsFromTestCase(SearchTest)
search_test_homepage = unittest.TestLoader().loadTestsFromTestCase(SearchTestHomePage)

smoke_tests = unittest.TestSuite([search_test, search_test_homepage])

unittest.TextTestRunner(verbosity=2).run(smoke_tests)

通過IDE我們執行這個指令碼:

在這個指令碼示例中:

我們使用TestSuites類來定義和執行測試套件,將多可測試加到一個測試套件中;還用TestLoader和TextTestRunner建立和執行測試套件;

2.6 使用unittest擴充套件來生成HTML格式的測試報告

基於之前的指令碼示例,我們基本可以體會unittest的強大,但對於輸出結果也許並不滿意,我們可能需要生成一個所有測試的執行結果作為報告發給同組的其他人員;因此我們需要一個格式更加友好的測試報告,既能夠檢視測試結果,又能深入各個細節;

我們可以使用unittest的擴充套件HTMLTestRunner來實現;

現在我們來修改上一個示例指令碼,並建立一個包含實際測試報告的輸出檔案:(searchtestsuiteshtml.py)

# -*- coding:utf-8 -*-

import unittest

import HTMLTestRunner
import os

from searchtest1 import SearchTest
from searchtest2 import SearchTestHomePage

from datetime import date

now = date.today()
datestr = now.strftime('%m-%d-%y')

dir = os.getcwd()

search_test = unittest.TestLoader().loadTestsFromTestCase(SearchTest)
search_test_homepage = unittest.TestLoader().loadTestsFromTestCase(SearchTestHomePage)

smoke_tests = unittest.TestSuite([search_test, search_test_homepage])

filepath = dir + "/SmokeTestReport{}.html".format(datestr)
with open(filepath, 'wb') as outfile:
    runner = HTMLTestRunner.HTMLTestRunner(stream=outfile, title='Title:Test Report', description='Des:Smoke Tests')
    runner.run(smoke_tests)

將下載的指令碼直接新增到工程使用可能會報錯,這是因為現在的HTMLTestRunner對應的是Python2的版本;

可以在這裡得到對應修改後的指令碼檔案;

執行指令碼我們得到了一個SmokeTestReport06-08-18.html的輸出檔案:

這就是我們預期生成的測試報告檔案;

關於斷言的使用,還很淺顯,需要結合頁面中不同型別的htnl元素進行斷言,接下來學習如何定義和使用定位器來與之互動;

2.7 上述指令碼中存在的問題

在後續和同事交流的實踐中,我們發現了一個問題,在這裡單獨作為一個小節,簡要說明下;

對於searchtest1.py這個指令碼,由於第二個測試用例是複製的第一個,所以在執行的時候,我並沒有發現什麼不對,但是如果把第二個測試用例的搜尋內容進行了修改,問題就會出現:重新submit之後的搜尋結果並沒有打印出來;

經過一番嘗試和修改,新的指令碼如下:

# -*- coding:utf-8 -*-

import unittest
from selenium import webdriver

import time


class SearchTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()
        cls.driver.implicitly_wait(15)
        cls.driver.maximize_window()

        cls.driver.get('http://www.baidu.com')

    def test_search_by_category(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.submit_field = self.driver.find_element_by_id("su")

        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')

        self.submit_field.submit()

        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")
        for product in products:
            print("1" + product.text)
        self.assertEqual(10, len(products), 'alert description tqg')

    def test_search_by_category1(self):
        self.search_field = self.driver.find_element_by_id("kw")
        self.submit_field = self.driver.find_element_by_id("su")

        self.search_field.clear()
        self.search_field.send_keys('路飛')

        self.submit_field.click()
        time.sleep(2)
        products = self.driver.find_elements_by_xpath("//div[contains(@class, 'c-abstract')]")

        for product in products:
            print("2" + product.text)

        self.assertEqual(6, len(products), 'alert description lufei')

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

if __name__ == '__main__':
    unittest.main(verbosity=2)

問題出在:

對於當前頁的搜尋submit之後,結果沒能返回的時候 就已經進行了斷言,顯然這是不對的;

我們修改使用搜索按鈕的click()方法,然後匯入time模組,呼叫sleep()方法強制等待2s,等待當前介面對“路飛”的搜尋結束之後在進行斷言;

相關聯的,這個問題引入了等待響應的方式問題,我們後續學習;

小結-序

伴隨著前兩章內容的實踐,我們瞭解到了一個基本的自動化測試指令碼是如何編寫、執行和使用的,我們要做的還有很多;接下來我們要學習更多高階的內容,包括元素定位、元素的等待機制等,在簡單略讀了整本參考書籍之後,還有很多優秀的第三方測試工具可以幫助我們更簡單、更強大的實現測試需求,鑑於對正本書的內容有了一個整體的認識,我將調整接下來筆記的梳理方式,更多的結合實際的測試場景去總結和學習,也方便大家交流!

三、元素定位

頁面元素:

web應用是包含 超文字標記語言(HTML)、層疊樣式表(CSS)、JavaScript指令碼組成的Web頁面集合;

基於的使用者互動有 跳轉到指定的 統一資源定位(URL)網站,單擊提交,向服務傳送請求,處理伺服器響應資源;

瀏覽器使用以上資源生成Web頁面,構建Web視覺元素;如 文字框 按鈕 標籤頁 圖示 複選框 單選按鈕 列表 圖片等;

這些視覺元素或控制元件都被Selenium稱為頁面元素(WebElements);

本章我們需要掌握的是:Selenium WebDriver定位元素的方法;如何用瀏覽器開發者模式輔助定位元素;

定位元素的方法其實有很多:通過id、name、class屬性定位,利用xpath和css選擇器定位;在定位到元素之後,我們可以使用Selenium WebDriver與之自動化互動;

在前兩章的學習過程中,我們已經使用過了一些元素定位的方法;在瀏覽器中我們可以通過檢視元素/原始檔的方式來檢視頁面結構;(具體的查詢更多的是靠對html文件結構的熟悉,多多閱讀前端頁面,好處多多)

Safari的開發模式也是很好用的;

3.1 元素定位

為了模擬使用者操作,我們需要告訴Selenium如何定位元素,如何檢視元素的屬性和狀態;

這裡再次將之前實踐的針對百度搜索的較完整測試指令碼拿過來進行說明;(TqgWebTestProject testBaiduSearch.py)

import unittest
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By

class BaiduSearchKeyword(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.driver = webdriver.Firefox()
        cls.driver.implicitly_wait(5)
        cls.driver.maximize_window()

        cls.driver.get('http://www.baidu.com')

    def is_element_present(self, how, what):
        try:
            self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e:
            return False
        return True

    def test_search_by_tqg_justify(self):
        self.assertTrue(self.is_element_present(By.ID, 'kw'))

    def test_search_by_tqg(self):
        self.search_field = self.driver.find_element_by_id('kw')
        self.submit_field = self.driver.find_element_by_id('su')

        self.search_field.clear()
        self.search_field.send_keys('銅錢貫')

        self.submit_field.click()

        products = self.driver.find_elements_by_xpath("//div[contains(@class,'c-abstract')]")
        self.assertTrue(self.driver.title.__contains__('銅錢貫'))
        for product in products:
            print("銅錢貫 查詢結果:" + product.text)

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ == '__main__':
    unittest.main(verbosity=2)

這個指令碼之前已經學習過,很簡單 兩個測試用例分別是 校驗元素是否存在 存在之後使用它進行搜尋,斷言搜尋結果中包含搜尋的指定關鍵字;

要搜尋一個產品,需要先找到搜尋框和搜尋按鈕,接著通過鍵盤輸入要查詢的關鍵字,最後用滑鼠單擊搜尋按鈕,提交搜尋請求;

這是人工的操作,我們希望Selenium能模擬這個過程,這就需要我們程式化地告訴Selenium如何定位,模擬滑鼠的動作等;

Selenium提供了很多find_element_by方法定位頁面元素,正常定位的話,相應的WebElement例項會被返回,反之將丟擲NoSuchElementException的異常;

Selenium還提供了多種find_elements_by方法去定位多個元素,返回的是list陣列;

8種find_element_by方法:

——find_element_by_id()

——find_element_by_name()

——find_element_by_class_name()

——find_element_by_tag_name()

——find_element_by_xpath()

——find_element_by_css_selector()

——find_element_by_link_text()#標籤之間的文字資訊

——find_element_by_partial_link_text()

find_elements_by方法按照一定的標準返回一組元素:

——find_elements_by_id()

——find_elements_by_name()

——find_elements_by_class_name()

——find_elements_by_tag_name()

——find_elements_by_xpath()

——find_elements_by_css_selector()

——find_elements_by_link_text()

——find_elements_by_partial_link_text()

我們可以通過瀏覽器產看html頁面元素,找到搜尋框(參照之前指令碼):

值得一提的是class定位:

class屬性是用來關聯CSS中定義的屬性的;

通過對元素ID、name、class屬性來查詢元素是最為普遍和快捷的方法;

也可以增加一個測試用例斷言元素的可用性:

    def test_search_by_tqg_enable(self):
        self.submit_field = self.driver.find_element_by_id('su')
        self.assertTrue(self.submit_field.is_enabled())