pytest框架整体设计及规划

一、研发pytest框架的两种场景

场景1:测试脚本已提交

场景2:测试脚本未研发

二、框架分层

1.pytest框架层:脚本层、配置层、测试报告层、数据驱动层、日志层

2.项目框架层:前台、后台、服务器端

三、梳理框架

1.收集现有脚本

2.执行顺序调整

3.数据集梳理

4.调用传参梳理

四、脚本优化

1.结构优化

2.数据集优化

3.检查点优化

4.测试报告优化

5.测试日志优化

五、框架分层思想

先是执行pytest.ini文件

再是执行conftest.py文件

再是执行框架驱动层,框架驱动层可以是有多个

用驱动去执行脚本层、公共模块层、数据层、测试报告、测试日志

六、前置方法初始化的各种设置

1.setup的初始化合并。

若干个脚本都需要打开登录页面,怎样把setup提取出来,可以放到configtest里面去driver=none,是把脚本setup初始化下的语句放到configtest里面,但是不能用脚本上的driver了,只能configtest里面的browser,这个browser在方法后面要以参数的形式,改好的东西,在你的框架文档里面说明一下版本变更,保持框架和文档的一致性

定好的设计后面就不要再改了,再改的话就不要叫browser了,再改的话就是自己定义的self.driver了,公共的地方不能随意改,要改的话,也到大家通过一致才能改

这里是conftest.py文件
 

这里是conftest.py文件


from selenium import webdriver
import pytest
driver = None


@pytest.fixture(scope='session', autouse=True)
def browser():
    global driver
    chrome_options=webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    if driver is None:
        driver = webdriver.Chrome()
        url = "http://testplt.share.atstudy.com/admin/login/?next=/admin/"
        driver.get(url)
    return driver

修改后的脚本

# 登录成功的selenium代码

from selenium import webdriver
import pytest

# 定义类
class Test_lei_login1():

    # # 初始化里面放一些公共的属性,一个类里面只执行一次
    # def setup_method(self):
        # # 定义url
        # self.url='http://testplt.share.atstudy.com/admin/login/?next=/admin/'
        # # 启动谷歌浏览器
        # self.driver=webdriver.Chrome()
        # # 窗口最大化
        # # self.driver.maximize_window()
        # # 访问url
        # self.driver.get(self.url)

    # 定义登录方法
    @pytest.mark.smoke1
    def test_login(self,browser):

        # selenium跟接口的发送请求,有什么区别吗?
        # 有区别,接口的发送请求是
        # 第一种
        # response=requests.post(url,data=)
        # 第二种
        # s=requests.session()
        # response=s.post(url,data=)
        # selenium的发送请求是这样的

        # 找到元素输入内容
        browser.find_element_by_name('username').send_keys('atstudy')
        browser.find_element_by_name('password').send_keys('51testing')
        browser.find_element_by_xpath('//*[@id="login-form"]/div[3]/input').click()

        # 找到实际的结果
        result=browser.find_element_by_xpath('//*[@id="content-main"]/div/table/caption/a').text

        # 来一个断言
        assert result=='测试平台'

    # # 场景后置
    # def teardown_method(self):
    #     self.driver.close()


if __name__ == '__main__':
    pytest.main(['test_login1.py','-s','-v'])



2.什么情况下,会初始化两个浏览器

在运行的时候,会先去执行configtest,会初始化一个浏览器对象,在你的脚本里面也会初始化一个浏览器对象

3.browser的释放

def test_login_1(self,browser):
        browser.close()

七、driver驱动文件

在驱动脚本文件上,pytest.main里面的路径是能是相对路径,这样脚本移植到另外一个路径也不会有变化,只要内部结构路径不变就ok

import pytest

if __name__ == '__main__':
    pytest.main(["-vs",'D:\PythonLearn\pytest_five\login\\test_login1.py','-m smoke1'])

八、pytest标签整合处理

1.脚本上的标签:@pytest.mark.smoke2.qy

2.驱动脚本上:pytest.main(['脚本名','参数名','-m smoke'])

如果pytest.ini文件的addops上,写了参数-m smoke ,那么驱动脚本上,对应的参数就不需要写

3.pytest.ini文件上:addopts=-vs -rs -m smoke   

九、测试报告及日报与测试框架的整合

1.在测试报告中添加一个feature

@allure.feature("标签说明")

这个标签是放在脚本的class上面的

脚本最上面需要导入一个allure的类库

# 登录成功的selenium代码

from selenium import webdriver
import pytest
import allure

# 定义类
@allure.feature("标签说明")
class Test_lei_login1():

2.生成测试报告所需要的数据,是在驱动脚本上面加上--alluredir=./a/b,

import pytest

if __name__ == '__main__':
    pytest.main(["-vs",'D:\PythonLearn\pytest_five\login\\test_login1.py','-m smoke1','--alluredir=./report'])

3.生成测试报告

以前都是在命令行中写,现在整合成框架

系统的对象要导进来,然后再是通过系统的system方法,输入生成测试报告的命令

生成测试报告的路径跟生成测试报告所需要的数据的路径得是一致的

import pytest
import os


if __name__ == '__main__':
    # pytest.main(["-vs",'D:\PythonLearn\pytest_five\login\\test_login1.py','-m smoke1','--alluredir=./report'])
    os.system('allure generate ./report')

4.如果想让每个脚本运行的时候,都能生成测试报告,可以把相关的命令放在pytest.ini文件里,addopts下

5.如何把我们的日志整合在脚本里面

1日志这个统一的配置,都可以放一个config文件,以后所有的脚本都得去写日志,所以就把模板定义下来,给日志定义一个相关的文件,因为在我们原来的试验的时候,这个.conf文件名不是固定的,可以起其他的名字,不像是说py的日志公共配置,默认的是conftest,一般来说,一个项目就是统一的一个日志,加在根目录下,对整个项目都是有效的

pytest框架整体设计及规划_第1张图片

2头文件要先复制过来,放到我们当前的脚本文件里面

import logging

import logging.config

3日志对象初始化的过程可以放到最上面,可以当做全局变量去用,在每一个需要打印出日志的代码输入日志输出语句

# 日志控制台输出的初始化
logging.config.fileConfig('logger.conf')
root_logger = logging.getLogger('root')

# 日志文件输出的初始化
logger = logging.getLogger('main')


# 定义类
@allure.feature("这是一个最基础的登录测试脚本")
class Test_lei_login1():
    # 定义登录方法
    @pytest.mark.smoke1
    def test_login(self,browser):
        # 找到元素输入内容
        browser.find_element_by_name('username').send_keys('atstudy')
        # 日志控制台输出
        root_logger.info("请输入用户名atstudy")
        # 日志文件输出
        logger.info("请输入用户名atstudy")
        browser.find_element_by_name('password').send_keys('51testing')
        root_logger.info("请输入密码atstudy")
        logger.info("请输入密码atstudy")
        browser.find_element_by_xpath('//*[@id="login-form"]/div[3]/input').click()
        root_logger.info("点击登录按钮")
        logger.info("点击登录按钮")
        # 找到实际的结果
        result=browser.find_element_by_xpath('//*[@id="content-main"]/div/table/caption/a').text
        root_logger.info("进行检查点验证")
        logger.info("进行检查点验证,实际结果:测试平台,预期结果:"+result)
        # 来一个断言
        assert result=='测试平台'

日志都是自己写出来的,是为了今后调试用的,如果出现错误了,就知道哪一个步骤错误了,

4.日志的变量反映到日志里面

        # 找到实际的结果
        result=browser.find_element_by_xpath('//*[@id="content-main"]/div/table/caption/a').text
        root_logger.info("进行检查点验证")
        logger.info("进行检查点验证,实际结果:测试平台,预期结果:"+result)
        # 来一个断言
        assert result=='测试平台'

5.日志总结,不是每个脚本都需要写日志,一般都是脚本比较复杂的脚本才需要写日志,来进调试用的

十、脚本的并发

脚本的内部可以并发,脚本和脚本之间没有相互干扰,脚本与脚本之间没有顺序控制

在多个机器上,按不同的目录去执行,并发不是一定需要,但是技术可以有一个扩展

当脚本支持并发,想让脚本执行更快一些

-n就是并发的数,建议一般不要超过5个,太大的话,你的内存cpu不够的话,反而速度会下降

因为他要初始化很多进程

pytest虽然提供给我们一个参数,非常方便,但是需要导入一个插件

import  pytest
import  time as t

def add(a,b):
   try:
      return a+b
   except Exception as e:
      return e.args[0]

@pytest.mark.parametrize('a,b,result',[
      (1,1,2),
      (1.0,1.0,2.0),
      (1, 1.0, 2.0),
      (1,0,1),
      ('','',''),
      ('hi ','wuya','hi wuya'),
      (0, '', "unsupported operand type(s) for +: 'int' and 'str'"),
      (1,'hi',"unsupported operand type(s) for +: 'int' and 'str'"),
       (1.0,'wuya',"unsupported operand type(s) for +: 'float' and 'str'"),
])
def test_add(a,b,result):
   t.sleep(1)
   assert  add(a,b)==result

#导入插件 pytest-xdist
if __name__=="__main__":
    # pytest.main(["-s","-v","test_conexe.py"])
    pytest.main(["-s","-v","-n=4","test_conexe.py"])

你可能感兴趣的:(pytest)