python+selenium+unittest自動化測試框架

前言

關於自動化測試的介紹,網上已有很多資料,這裏不再贅述,UI自動化測試是自動化測試的一種,也是測試金字塔最上面的一層,selenium是應用於web的自動化測試工具,支持多平臺、多瀏覽器、多語言來實現自動化,優點如下:

①開源、免費且對web界面有良好的支持;;

②多瀏覽器支持:chrome、Firefox、IE、Edge等;

③多平臺支持:Linux、Windows、MAC;

④多語言支持:java、python、Ruby、C#、JavaScript、C++;

⑤簡單(API簡單)、靈活(開發語言驅動),支持分佈式測試用例執行; 

selenium官方中文文檔:http://selenium-python-zh.readthedocs.io/en/latest/index.html 

環境準備

  • 瀏覽器(Chrome)
  • Python
  • Selenium
  • chromedriver(請下載於Chrome對應版本的驅動)
  • IDE(Pycharm)

1、python、pycharm安裝 
Python官網下載鏈接:https://www.python.org/downloads/windows/ 
pycharm官網下載鏈接:https://www.jetbrains.com/pycharm/download/#section=windows 

2、selenium安裝 

pip install selenium 

關於selenium元素定位是開展web自動化測試的基礎和關鍵,總共有八種定位方式,包括id,class,xpath等,可以參考網上資料學習,這裏不再贅述。

3、chromedriver驅動安裝

驅動下載:http://chromedriver.storage.googleapis.com/index.html

然後把chromedriver.exe拷貝到到chrome的安裝目錄下…\Google\Chrome\Application\ ,同時把chrome的安裝目錄加入到path環境變量。

4、快速驗證測試

自動化測試框架

  • config目錄中存放的是測試配置相關的文件,文件類型ini,包括測試的網址、瀏覽器驅動等信息
  • framework目錄中存放的是頁面基礎類base_page: 封裝一些常用的頁面操作方法;日誌類 Logger: 封裝日誌輸出及控制檯輸出方法
  • logs用來存放輸出的日誌文件
  • pageobjects目錄存放的是頁面對象,一個頁面封裝爲一個類,一個元素封裝爲一個方法
  • screenshots目錄存放的是測試過程中的相關截圖
  • test_report用來存放輸出的測試報告
  • testsuites目錄存放測試用例,包括test_base和單個測試用例

1、config.ini配置信息如下:

2、framework目錄下base_page的封裝:

import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.select import Select
import os.path
from framework.logger import Logger

# 創建一個日誌實例
logger = Logger(logger="BasePage").getlog()

class BasePage(object):
    """
    定義一個頁面基類,讓所有頁面都繼承這個類,封裝一些常用的頁面操作方法
    """
    def __init__(self, driver):
        self.driver = driver

        #get an url link
    def open(self,url):
        self.driver.get(url)

        #quit browser and end testing
    def quit_browser(self):
        self.driver.quit()

        # 瀏覽器前進操作
    def forward(self):
        self.driver.forward()
        logger.info("Click forward on current page.")

        # 瀏覽器後退操作
    def back(self):
        self.driver.back()
        logger.info("Click back on current page.")

        # 顯示等待
    def wait(self,loc,seconds):
        try:
            wait_=WebDriverWait(self.driver,seconds)
            wait_.until(lambda driver:driver.find_element(*loc))
            logger.info("wait for %d seconds." % seconds)
        except NameError as e:
            logger.error("Failed to load the element with %s" % e)

        # 保存圖片
    def get_windows_img(self):
        """
        把file_path保存到我們項目根目錄的一個文件夾.\Screenshots下
        """
        file_path = os.path.dirname(os.path.abspath('.')) + 'Selenium/screenshots/'
        rq = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
        screen_name = file_path + rq + '.png'
        try:
            self.driver.get_screenshot_as_file(screen_name)
            logger.info("Had take screenshot and save to folder : /screenshots")
        except NameError as e:
            logger.error("Failed to take screenshot! %s" % e)
            self.get_windows_img()

         # 定位元素方法
    def find_element(self,loc):
        """
        :return: element
        """
        return self.driver.find_element(*loc)

        # 輸入
    def send_keys(self, selector, text):

        el = self.find_element(selector)
        el.clear()
        try:
            el.send_keys(text)
            logger.info("Had type \' %s \' in inputBox" % text)
        except NameError as e:
            logger.error("Failed to select in input box with %s" % e)
            self.get_windows_img()

        # 清除文本框
    def clear(self, selector):

        el = self.find_element(selector)
        try:
            el.clear()
            logger.info("Clear text in input box before typing.")
        except NameError as e:
            logger.error("Failed to clear in input box with %s" % e)
            self.get_windows_img()

        # 點擊元素
    def click(self, selector):

        el = self.find_element(selector)
        try:
            el.click()
            logger.info("The element \'%s\' was clicked." % el.text)
        except NameError as e:
            logger.error("Failed to click the element with %s" % e)


        #鼠標事件(左鍵點擊)
    def move_element(self,loc,sloc):
        mouse=self.find_element(loc)
        try:
            ActionChains(self.driver).move_to_element(mouse).perform()
            self.click(sloc)
            pass
        except Exception as e:
            logger.error("Failed to click move_element with %s" % e)
            self.get_windows_img()

        # 強制等待
    @staticmethod
    def sleep(seconds):
        time.sleep(seconds)
        logger.info("Sleep for %d seconds" % seconds)

logger日誌輸入方法:

import logging
import os.path
import time

class Logger(object):
    def __init__(self, logger):
        '''''
            指定保存日誌的文件路徑,日誌級別,以及調用文件
            將日誌存入到指定的文件中
        '''
        # 創建一個logger
        self.logger = logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)

        # 創建一個handler,用於寫入日誌文件
        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
        log_path = os.path.dirname(os.path.abspath('.')) + 'Selenium/logs/'
        log_name = log_path + rq + '.log'
        fh = logging.FileHandler(log_name)
        fh.setLevel(logging.INFO)

        # 再創建一個handler,用於輸出到控制檯
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)

        # 定義handler的輸出格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)

        # 給logger添加handler
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)

    def getlog(self):
        return self.logger

3、關於頁面對象的寫法參考:

頁面對象繼承於base_page基類

from framework.base_page import BasePage
from selenium.webdriver.common.by import By
from framework.logger import Logger

logger = Logger(logger="cloud_page").getlog()
class Cloud(BasePage):
    #定位器
    input_box = (By.ID,'kw')
    search_submit = (By.XPATH,'//*[@id="su"]')

    def value_input(self, text):
        self.wait(self.input_box,5)
        self.send_keys(self.input_box, text)

    def submit_btn(self):
        self.click(self.search_submit)
        logger.info("show results!")
        self.sleep(2)

4、testsuite部分,每個用例都要執行的用例前的準備setup和清理teardown寫在test_base文件裏,單個測試用例文件繼承於它

from selenium import webdriver
import unittest

class TestBase(unittest.TestCase):
    def setUp(self):
        self.driver=webdriver.Chrome()   #驅動瀏覽器
        self.driver.implicitly_wait(10)  #設置隱式等待
        self.driver.maximize_window()    #最大化瀏覽器

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

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

測試用例參考,注意測試用例方法命名一定要以test開頭

import time
from testsuites.test_base import TestBase
from pageobjects.baidu_page import Cloud

class BaiduSearch(TestBase):

    def test_baidu_search(self):
        """
        這裏一定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。
        :return:
        """
        input = Cloud(self.driver)
        input.open('https://www.baidu.com/')
        input.value_input('selenium')  # 調用頁面對象中的方法
        input.submit_btn()  # 調用頁面對象類中的點擊搜索按鈕方法
        time.sleep(2)
        input.get_windows_img()  # 調用基類截圖方法
        try:
            assert 'selenium' in 'selenium'
            print('Test Pass.')
        except Exception as e:
            print('Test Fail.', format(e))

5、最後就是核心代碼,testrunner.py 用來批量執行測試用例,引用HTMLTestRunner模塊生成測試報告。

import unittest
from HTMLTestRunner import HTMLTestRunner
import time
import os

# 定義輸出的文件位置和名字
DIR = os.path.dirname(os.path.abspath(__file__))
now = time.strftime("%Y%m%d%H%M", time.localtime(time.time()))

filename =now+"report.html"
#discover方法執行測試套件
testsuite = unittest.defaultTestLoader.discover(
   start_dir='./testsuites',
   pattern='*case.py',
   top_level_dir=None
   )

with open(DIR+'/test_report/'+filename,'wb') as f:
    runner = HTMLTestRunner(
       stream=f,
       verbosity=2, 
       title='gateway UI report',
       description='執行情況',
       tester='tester'
   )
    runner.run(testsuite)

6、測試報告展示

總結

基於selenium實現的web自動化框架不僅輕量級而且靈活,可以快速的開發自動化測試用例。本篇中的框架設計比較簡單,希望對大家以後的web自動化框架的設計和實現有所幫助,共同交流,共同進步!

今天要比昨天有進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章