Selenium与 unittest 框架的整合应用案例

来源:《全栈 UI 自动化测试实战》一书中讲解的框架及案例代码实现:

一、框架结构:

本示例框架共分为 5 个组成模块:
① bin(运行管理模块)
② case(用例管理模块)
③ data(数据存储模块)
④ report(结果返回模块)
⑤ utils(功能扩展模块)

框架.png

框架展开.png

二、案例:

以百度网页搜索页面和百度新闻搜索页面为例

代码实现:

代码使用的 sleep 时间强制等待是为了测试方便,实际应用最好不要使用。

代码格式化快捷键:command+option+L或 ctrl+alt+L

1.case 模块用例:

case 模块实现思路:
以百度网页搜索页面和百度新闻搜索页面为例,分别将搜索内容进行参数化处理。

  • 实现百度新闻模块测试用例:
# 第九章------9.2 ------case 模块用例----实现百度新闻模块测试用例
# 第九章/test_baidu_new.py

import unittest
import ddt
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By

from Chapter9.framework_unit.utils.excel_read import ParseExcel

# 导入 data 模块 test_data.xlsx中的测试数据
excelPath = './../data/test_data.xlsx'
sheetName = 'data_new'
excel = ParseExcel(excelPath,sheetName)

# 使用 ddt 方式循环导入数据
@ddt.ddt
class Test_Baidu_News(unittest.TestCase):
        @classmethod
        def setUpClass(self):
            self.driver = webdriver.Firefox()

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

        def setUp(self):
            self.driver.get(url='https://news.baidu.com/')
            sleep(2)

        def tearDown(self):
            pass

        @ddt.data(* excel.getDataFromSheet())
        def test_sou(self,data):
            self.driver.find_element(By.ID,'ww').send_keys(data)
            sleep(2)
            self.driver.find_element(By.ID,'s_btn_wr').click()
            sleep(2)
            self.assertEqual('百度资讯搜索_'+data,self.driver.title)

if __name__ == '__main__':
    unittest.main()
  • 实现百度搜索模块测试用例:
# 第九章------9.2 ------case 模块用例----实现百度搜索模块测试用例
# 第九章/test_baidu_sou.py

import unittest
import ddt
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from Chapter9.framework_unit.utils.excel_read import ParseExcel
from Chapter9.framework_unit.utils.log import Log

# 导入 data 模块 test_data.xlsx中的测试数据
excelPath = './../data/test_data.xlsx'
# excelPath = './../data/test_data_sou.xlsx'
sheetName = 'data_sou'
excel = ParseExcel(excelPath,sheetName)

# 使用 ddt 方式循环导入数据
@ddt.ddt
class Test_Baidu_Search(unittest.TestCase):
        '''百度搜索用例'''

        @classmethod
        def setUpClass(self):
            self.driver = webdriver.Firefox()
            self.log = Log()

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

        def setUp(self):
            self.driver.get(url='https://www.baidu.com/')
            sleep(2)

        def tearDown(self):
            pass

        @ddt.data(* excel.getDataFromSheet_mul())
        def test_sou(self,data):
            '''搜索方式'''
            print("data[0]:", data[0])
            try:
                self.driver.find_element(By.ID,'chat-textarea').send_keys(data[0])
                sleep(2)
                self.driver.find_element(By.ID,'chat-submit-button').click()
                sleep(2)
                self.assertEqual(data[0]+'_百度搜索',self.driver.title)
                print('try--assertEqual:---',data[0]+'_百度搜索',self.driver.title)
            except AssertionError as e:
                self.log.add_log(data[0],data[1],format(e))
                self.assertEqual(data[0]+'_百度搜索',self.driver.title)
                print('except--AssertionError--assertEqual:---',data[0]+'_百度搜索',self.driver.title)
            else:
                print('用例执行成功')
                self.log.add_log(data[0],data[1],'用例执行成功')


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

2. data 模块数据:

data模块实现思路:
data 模块以 Excel 文件作为数据管理媒介,在 Excel 文件中新建 data_sou和 data_new两张表,分别用来存放用例执行模块的搜索数据。Excel 存放数据表如下图:(sheet 名不要有空格)

图片1.png

图片.png

3. report 模块:

report模块实现思路:
report 模块中主要存放 3 种返回数据,分别是 HTML 结果页面、执行异常截图和执行过程日志记录

例如运行代码后生成的 log文件:


图片.png

4. uitls功能模块:

utils模块实现思路:
utils 模块主要用来存放一些框架运行过程中的辅助功能。
本章自动化测试框架中主要实现了 Excel表格数据的读取、初始化目录、日志记录功能。

  • 数据读取功能:
    Excel数据读取的讲解会在第 16 章数据驱动里进行详细演示。此处仅展示框架中数据读取功能的实现。
# 第九章---9.5---utils 功能模块---9.5.1 数据读取功能

# 第九章/excel_read.py

from openpyxl import load_workbook

class ParseExcel():
    # 声明 ParseExcel 对象时传入 Excel 文件路径及表名
    def __init__(self,excel_path,sheetName):
        self.wb = load_workbook(excel_path)
        self.sheet = self.wb[sheetName]

    # 将表中数据处理成一维列表
    # 此方法用来处理 data_new 表中数据
    def getDataFromSheet(self):
        dataList = []
        for line in self.sheet:
            dataList.append(line[0].value)
        # 清空表头数据
        dataList.pop(0)
        return dataList

    # 将表中数据处理成二维列表
    # 将此方法用来处理 data_sou 表中数据
    # 此方法适用于处理传入数据中自带预期数据情况
    def getDataFromSheet_mul(self):
        dataList = []
        for line in self.sheet:
            tmp_list = []
            tmp_list.append(line[0].value)
            tmp_list.append(line[1].value)
            dataList.append(tmp_list)
        dataList.pop(0)
        return dataList

if __name__ == '__main__':
    excel_path = './../data/test_data.xlsx'
    sheetName = 'data_new'
    pe = ParseExcel(excel_path,sheetName)
    print(pe.getDataFromSheet())


  • 初始化目录:
    在 report 模块中记录返回数据时,首先会创建与日期同名目录,再将返回数据存在目录下面。
    此方法通常用在所有用例开始执行前,具体使用方法见代码 run_all_case.py。

# 第九章 9.5.2 初始化目录
# 第九章/init_folder.py

import os

def init_folder(date):
    # 创建 html 目录位置
    html_folder_path = './../report/html/'

    # 将所创建的子目录添加时间标记
    folder_path = html_folder_path + date

    # 判断当前日期目录是否存在,不存在则创建
    if not os.path.exists(folder_path):
        os.mkdir(folder_path)

    # 创建 png 目录位置
    png_folder_path = './../report/png/'
    folder_path = png_folder_path + date

    # 判断当前日期目录是否存在,不存在则创建
    if not os.path.exists(folder_path):
        os.mkdir(folder_path)

    # 创建 log 目录位置
    log_folder_path = './../report/log/'
    folder_path = log_folder_path + date

    # 判断当前目录是否存在,不存在则创建
    if not os.path.exists(folder_path):
        os.mkdir(folder_path)


  • 日志记录功能
    实现日志记录功能,代码如下:
# 第 9 章---9.5.3----日志记录功能
# 第九章/log.py
# logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
# level:设置日志级别
# format:指定handler使用的日志显示格式
# datefmt:指定日期时间格式,如果format参数中存在asctime,则需要指定时间格式
# filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中
# filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”

import logging
import datetime

class Log():
    def __init__(self):
        
        data = datetime.datetime.now().strftime('%Y-%m-%d')
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s %(levelname)s %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S',
            filename='./../report/log/' + data + '/test.log',
            filemode='w'
        )

    def add_log(self, page,func,des):
        out_str = page + ':' + func + ':' + des
        logging.info(out_str)


5.bin 运行模块:

用例在执行时会根据具体情况选择执行部分或全部测试用例。
这种需求最快的实现方式是编写多个 run 文件,每个 run 文件的执行范围不同。
因为HTMLTestRunner下载失败,暂时不生成 html 了

  • 创建执行范围为百度新闻模块用例的 run 文件:
# 第九章---9.6-----bin 运行模块----

# 第九章/run_new.py
import unittest
import datetime
from Chapter9.framework_unit.utils.init_folder import init_folder

dir = './../case/'
# 创建测试套件 suite
suite = unittest.TestLoader().discover(start_dir=dir, pattern='test_baidu_new.py')

if __name__ == '__main__':
    date_time = datetime.datetime.now()
    date = date_time.strftime('%Y-%m-%d')
    report_time = date_time.strftime('%H:%M:%S')
    init_folder(date)
    # 创建测试套件运行器
    runner = unittest.TextTestRunner()
    # 调用 run()方法运行 suite 测试套件中的用例
    runner.run(suite)

# # HTMLTestRunner 无法下载,且报错暂时不用------------
# import unittest
# import datetime
# import HTMLTestRunner
# from Chapter9.framework_unit.utils.init_folder import init_folder
#
# suite = unittest.defaultTestLoader.discover('./../case/',pattern='test_baidu_new.py')
#
# if __name__ == '__main__':
#
#   date_time = datetime.datetime.now()
#   date = date_time.strftime('%Y-%m-%d')
#   report_time = date_time.strftime('%H%M%S')
#   init_folder(date)
#   fp = open('./../report/html/' + date + '/' + report_time + 'report.html', 'wb')
#   runner = HTMLTestRunner.HTMLTestRunner(
#       stream=fp,
#       title='test.html',
#       description='text')
#   runner.run(suite)
#   fp.close()

  • 创建执行范围为百度新搜索模块用例的 run 文件:
# 第九章---9.6-----bin 运行模块----
#
# 第九章/run_sou.py
import unittest
import datetime
from Chapter9.framework_unit.utils.init_folder import init_folder

dir = './../case/'
# 创建测试套件 suite
suite = unittest.TestLoader().discover(start_dir=dir, pattern='test_baidu_sou.py')

if __name__ == '__main__':
    date_time = datetime.datetime.now()
    date = date_time.strftime('%Y-%m-%d')
    report_time = date_time.strftime('%H:%M:%S')
    init_folder(date)
    # 创建测试套件运行器
    runner = unittest.TextTestRunner()
    # 调用 run()方法运行 suite 测试套件中的用例
    runner.run(suite)



#
# # HTMLTestRunner 无法下载,且报错暂时不用------------------------
# import unittest
# import datetime
# import HTMLTestRunner
# from Chapter9.framework_unit.utils.init_folder import init_folder
#
# suite = unittest.defaultTestLoader.discover('./../case/',pattern='test_baidu_sou.py')
#
# if __name__ == '__main__':
#
#   date_time = datetime.datetime.now()
#   date = date_time.strftime('%Y-%m-%d')
#   report_time = date_time.strftime('%H%M%S')
#   init_folder(date)
#   fp = open('./../report/html/' + date + '/' + report_time + 'report.html', 'wb')
#   runner = HTMLTestRunner.HTMLTestRunner(
#       stream=fp,
#       title='text.html',
#       description='text')
#   runner.run(suite)
#   fp.close()

  • 创建执行范围为所有模块用例的 run 文件:

# 第九章---9.6-----bin 运行模块----

# 第九章/run_all-case.py

import unittest
import datetime
from Chapter9.framework_unit.utils.init_folder import init_folder

dir = './../case/'
# 创建测试套件 suite
suite = unittest.TestLoader().discover(start_dir=dir, pattern='test_baidu_*.py')

if __name__ == '__main__':

    date_time = datetime.datetime.now()
    date = date_time.strftime('%Y-%m-%d')
    report_time = date_time.strftime('%H:%M:%S')
    init_folder(date)
    # 创建测试套件运行器
    runner = unittest.TextTestRunner()
    # 调用 run()方法运行 suite 测试套件中的用例
    runner.run(suite)



# # HTMLTestRunner 无法下载,且报错暂时不用---------
# import unittest
# import datetime
# import HTMLTestRunner#下载失败,报错
# from Chapter9.framework_unit.utils.init_folder import init_folder
#
# suite = unittest.defaultTestLoader.discover('./../case/',pattern='test_baidu_*.py')
#
# if __name__ == '__main__':
#
#   date_time = datetime.datetime.now()
#   date = date_time.strftime('%Y-%m-%d')
#   report_time = date_time.strftime('%H%M%S')
#   init_folder(date)
#   fp = open('./../report/html/' + date + '/' + report_time + 'report.html', 'wb')
#   runner = HTMLTestRunner.HTMLTestRunner(
#       stream=fp,
#       title='test.html',
#       description='text')
#   runner.run(suite)
#   fp.close()

6.运行结果显示:

以全部用例运行为例(run_all-case.py)

所有用例运行结果.png

生成的日志log文件:


日志.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容