pytest + allure +selenium uiAutoTest分享

框架 pytest + allure + selenium 和 po设计思想–这个这个基类页面我还没写,所以没封装页面操作类方法,浏览器驱动的切换封装,小伙伴有兴趣可以自己研究一下顺便加一下

目录

1.conftest.py - 进行浏览器驱动封装,以及各种回调函数

import os
import pytest
from selenium import webdriver
from py._xmlgen import html
import allure
from common import configPath
@pytest.fixture(scope='function',autouse=True)
def browser():
    # 静默执行
    option = webdriver.ChromeOptions()
    option.add_argument('headless')
    global _driver
    _driver = None
    if _driver is None:
        _driver = webdriver.Chrome(chrome_options=option)
        _driver.implicitly_wait(10)
        _driver.get('https://mail.qq.com/')
        _driver.maximize_window()
    yield _driver
    _driver.quit()
    _driver = None

# 钩子函数 添加工作环境 environment.properities
def pytest_sessionfinish():
    r = configPath.ROOT_DIR
    with open(r + "/report/allure-raw/environment.properties", "w") as f:
        f.write("browser=chrome\nautor=wanfeng\ndomain=https://mail.qq.com/")


# allure 失败用例自动截图
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    '''
    获取每个用例状态的钩子函数
    :param item:
    :param call:
    :return:
    '''
    # 获取钩子方法的调用结果
    outcome = yield
    rep = outcome.get_result()
    # 仅仅获取用例call 执行结果是失败的情况, 不包含 setup/teardown
    if rep.when == "call" and rep.failed:
        mode = "a" if os.path.exists("failures") else "w"
        with open("failures", mode) as f:
            # let's also access a fixture for the fun of it
            if "tmpdir" in item.fixturenames:
                extra = " (%s)" % item.funcargs["tmpdir"]
            else:
                extra = ""
            f.write(rep.nodeid + extra + "\n")
        # 添加allure报告截图
        if hasattr(_driver, "get_screenshot_as_png"):
            with allure.step('添加失败截图'):
                allure.attach(_driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)

2.test_login.py - 调用封装方法

import time
from tools.setLog import Logger
from common.operateExcel import OperateExcel
import pytest
import allure
from selenium.webdriver.common.by import By
from page.loginPage import *
# 初始化日志
logger = Logger().getlog()

@allure.feature('登录功能')
@allure.testcase('https://mail.qq.com/', 'qq邮箱')
class Test_login():
    if isCase1Execute:
        @allure.severity(severity_level='normal')
        @allure.story('用例1:{}'.format(case1))
        @allure.title('#{}'.format(case1))
        def test_correct_login(self, browser):
            '''正确账号、密码'''
            browser.switch_to.frame(id)
            with allure.step("输入账号"):
                ac = browser.find_element(account[0], account[1])
                ac.clear()
                ac.send_keys(case1Account[0])
            with allure.step("输入密码"):
                pw = browser.find_element(password[0], password[1])
                pw.clear()
                pw.send_keys(case1Account[1])
            with allure.step("点击登录按钮"):
                bt = browser.find_element(button[0], button[1])
                bt.click()
            with allure.step("校验结果"):
                try:
                    time.sleep(1)
                    t1 = browser.title
                    assert "QQ邮箱" == t1, '没有登录进去'
                    OperateExcel().write_result(sheet_name='登录模块用例', id='DL-DLYM-001', value='pass')
                    logger.info('登录成功')
                except Exception as e:
                    logger.info(e)
                    OperateExcel().write_result(sheet_name='登录模块用例', id='DL-DLYM-001', value='fail')
    else:
        logger.info('此用例IsExecute:{},不执行!'.format(isCase1Execute))

    if isCase1Execute:
        @allure.story('用例2:{}'.format(case2))
        @allure.title('#{}'.format(case2))
        # @pytest.mark.skip
        def test_error_account(self, browser):
            '''错误的账号'''
            browser.switch_to.frame(id)
            ac = browser.find_element(account[0], account[1])
            ac.clear()
            ac.send_keys(case2Account[0])
            pw = browser.find_element(password[0], password[1])
            pw.clear()
            pw.send_keys(case2Account[1])
            bt = browser.find_element(button[0], button[1])
            bt.click()
            time.sleep(3)
            try:
                err = browser.find_element(error_msg[0], error_msg[1]).text
                logger.info(err)
                time.sleep(1)
                t1 = browser.title
                assert "QQ邮箱" == t1, '没有登录进去'
            except Exception as e:
                OperateExcel().write_result(sheet_name='登录模块用例', id='DL-DLYM-002', value='fail')
                logger.info(e)
    else:

3.loginPage.py - 存放页面元素,存放excel提取login数据

from selenium.webdriver.common.by import By
from common.operateExcel import OperateExcel

# 账号元素
account = (By.XPATH, '//*[@id="u"]')
# 密码元素
password = (By.XPATH, '//*[@id="p"]')
# 登录按钮
button = (By.XPATH, '//*[@id="login_button"]')
# 错误信息提示
error_msg = (By.XPATH, '//*[@id="err_m"]')
# iframe
id = 'login_frame'
# 断言值:名字
name = (By.XPATH, '//*[@id="useralias"]')

# 测试用例名称
case1 = OperateExcel().get_test_case(sheet_name='登录模块用例', id='DL-DLYM-001')
case2 = OperateExcel().get_test_case(sheet_name='登录模块用例', id='DL-DLYM-002')
case3 = OperateExcel().get_test_case(sheet_name='登录模块用例', id='DL-DLYM-003')
case4 = OperateExcel().get_test_case(sheet_name='登录模块用例', id='DL-DLYM-004')
case5 = OperateExcel().get_test_case(sheet_name='登录模块用例', id='DL-DLYM-005')
# 账号密码
case1Account = OperateExcel().get_account_data(sheet_name='登录模块用例', id='DL-DLYM-001')
case2Account = OperateExcel().get_account_data(sheet_name='登录模块用例', id='DL-DLYM-002')
case3Account = OperateExcel().get_account_data(sheet_name='登录模块用例', id='DL-DLYM-003')
case4Account = OperateExcel().get_account_data(sheet_name='登录模块用例', id='DL-DLYM-004')
case5Account = OperateExcel().get_account_data(sheet_name='登录模块用例', id='DL-DLYM-005')
# 是否执行
isCase1Execute = OperateExcel().get_is_execute(sheet_name='登录模块用例', id='DL-DLYM-001')
isCase2Execute = OperateExcel().get_is_execute(sheet_name='登录模块用例', id='DL-DLYM-002')
isCase3Execute = OperateExcel().get_is_execute(sheet_name='登录模块用例', id='DL-DLYM-003')
isCase4Execute = OperateExcel().get_is_execute(sheet_name='登录模块用例', id='DL-DLYM-004')
isCase5Execute = OperateExcel().get_is_execute(sheet_name='登录模块用例', id='DL-DLYM-005')

4.Excel数据存放 - 密码打码了,嘿嘿

pytest + allure +selenium uiAutoTest分享

5.operateExcel.py - 对excel进行读写操作

import datetime
import os
import time
from datetime import date

import pytest
from openpyxl import load_workbook
from openpyxl.styles import Font, colors
from common import configPath

class Variable():
   # excel中每列数据对应的索引
   id = 1
   testCase = 3
   priority = 4
   Account = 5
   Password = 6
   Expect = 7
   isExecute = 8
   TestResult = 9

   # test_result = 2

#操作Excel数据
class OperateExcel:
   def __init__(self):
       self.file_path = configPath.excel_path
       self.wb = load_workbook(self.file_path)

  # 获取一列数据
  def get_column_value(self, sheet_name, col_num):
      sh = self.wb[sheet_name]
      case = []
      for i in range(1, sh.max_row + 1):
          value = sh.cell(i, col_num).value
          case.append(value)
      return case

  # 获取id的序列(从而确定这一行数据)
  def get_rowId_index(self, sheet_name, id):
     idx = Variable.id
     allIdList = self.get_column_value(sheet_name, col_num=idx)
     if id not in allIdList:
         raise TypeError('编号:{},不存在!'.format(id))
     else:
         idIndex = allIdList.index(id) + 1
         return idIndex

 # 获取一行数据
 def get_row_value(self, sheet_name, row_num):
     sh = self.wb[sheet_name]
     case = []
     for i in range(1, sh.max_column + 1):
         value = sh.cell(row_num, i).value
         case.append(value)
     return case

 # 获取单元格数据
 def get_cell_value(self, sheet_name, col_num, row_num):
     sh = self.wb[sheet_name]
     value = sh.cell(row_num, col_num).value
     return value

 # 获取是否执行用例字段
 def get_is_execute(self,sheet_name,id):
     sh = self.wb[sheet_name]
     isExecute = sh.cell(self.get_rowId_index(sheet_name,id) + 1,Variable.isExecute).value
     if isExecute.lower() == "no":
         flag = False
     elif isExecute.lower() == "yes":
         flag = True
     else:
         raise TypeError("用户编号为:{} 的 ‘ IsExecute ’ 字段有误!允许类型:yes、no ".format(id))
     return flag

 # 获取测试用例字段
 def get_test_case(self,sheet_name,id):
     sh = self.wb[sheet_name]
     testCase = sh.cell(self.get_rowId_index(sheet_name,id) + 1,Variable.testCase).value
     return testCase

 # 获取账号密码字段
 def get_account_data(self,sheet_name,id):
     sh = self.wb[sheet_name]
     data = []
     account = sh.cell(self.get_rowId_index(sheet_name,id) + 1,Variable.Account).value
     data.append(account)
     password = sh.cell(self.get_rowId_index(sheet_name,id) + 1,Variable.Password).value
     data.append(password)
     for i in range(len(data)):
         if data[i] is None:
             data[i] = ''
         return data

 # 写入单元格数据
 def write_result(self, sheet_name, id, value):
     """
     @param sheet_name: Sheet表名称
     @param id:用例编号
     @param value: fail or pass
     """

     sh = self.wb[sheet_name]
     # 设置时间格式
     curTime = datetime.datetime.now().strftime('%Y%m%d %H:%M:%S')
     # 横,纵坐标
     y = self.get_rowId_index(sheet_name, id) + 1
     x = Variable.TestResult
     # 写入
     sh.cell(y, x).value = curTime + "->" + value
     # 设置字体样式
     if value.lower() == 'fail':
         v = sh.cell(y, x)
         v.font = Font(name='Arial', color=colors.RED, size=10)
     elif value.lower() == 'pass':
         v = sh.cell(y, x)
         v.font = Font(name='Arial', color="00B050",size=10)
     else:
         raise TypeError('请传入fail,pass,不区分大小写')
     # 保存
     print('保存数据,执行成功')
     self.wb.save(self.file_path)

总结:下载pytest-html插件也是可以生成美丽的报告,这里我使用的是allure好看一点点嘿嘿,后期也能在jenkins上集成,然后验证码这一块暂时没深入研究,测试的时候让开发先注释掉就可以了,这里只是模拟一个项目的登录部分。

顺便展示一波Allure好看的报告
pytest + allure +selenium uiAutoTest分享

上一篇:python自动化之如何利用allure生成测试报告


下一篇:form表单提交时后台类型报错