目录
概述
本文介绍了Python自动化测试环境的搭建及测试框架的使用方法。主要内容包括:1. 环境准备:下载安装Python(建议3.11以下版本)、Allure测试报告框架及Java虚拟机,并配置相关环境变量;2. 测试框架结构:详细说明了代码目录结构(conf、libs、script、test_case等)和关键文件(conftest.py、run_test_01_demo.sh);3. 测试用例编写:展示了一个包含3个测试用例的示例代码,说明了测试初始化和清理操作;4. 测试执行:介绍了通过shell脚本运行测试并生成Allure和pytest两种格式的测试报告。文章通过具体代码示例,完整呈现了从环境搭建到测试执行的自动化测试流程。
1 安装环境
1.1 安装Python
1.1.1 python的下载
https://www.python.org/
可以选择如下版本,高版本目前处于评测阶段
Windows环境下的下载地址:建议选择下载3.11以下的版本
https://www.python.org/downloads/windows/
1.1.2 安装Python
下载完成后,点击安装包,安装软件。建议选择如下安装方式。
配置安装参数:
安装完成后,检查环境配置参数:
安装完成后,在powershell中验证python是否安装完毕:
1) 使用如下命令,检测python版本
python --version
2) 直接敲击python:
python
1.2 Allure安装
1.2.1 下载软件包
1)下载allure,下载地址如下:
https://github.com/allure-framework/allure2/releases
2)安装java虚拟机,下载地址:
https://www.oracle.com/cn/java/technologies/downloads/#jdk24-windows
1.2.2 配置Allure
下载完成allure包后,解压该文件
配置其环境变量:
在powershell环境下验证allure的功能,在控制台输入如下命令:
allure
控制台显示如下信息说明,allure安装成功。
1.3 pytest架构相关的packet安装
在控制台输入如下命令,在进行安装python的第三方packet之前,首先执行如下命令:
python -m pip install --upgrade pip
然后使用如下命令安装packet:
pip install xxxx
查询系统用安装的packet
pip list
Package Version
--------------------- -------
allure-pytest 2.14.2
allure-python-commons 2.14.2
attrs 25.3.0
colorama 0.4.6
coloredlogs 15.0.1
exceptiongroup 1.3.0
humanfriendly 10.0
iniconfig 2.1.0
packaging 25.0
pip 25.1.1
pluggy 1.6.0
pyreadline3 3.5.4
pytest 8.3.5
PyYAML 6.0.2
setuptools 58.1.0
tomli 2.2.1
typing_extensions 4.13.2
2 Auto test 框架
2.1 代码架构
conf目录: 配置参数,使用.yml或者.ini文件格式
libs目录: 和项目相关的功能库代码
script目录: 操作case相关的脚本文件,文件格式为.sh
test_case目录: case相关的代码,用于编写case代码
conftest.py: 系统入口文件,用于初始化设备和加载参数
run_test_01_demo.sh: case运行文件
2.2 conftest.py 文件介绍
代码3~8行: 引用公共包
代码11~15: 参数入口函数
代码21~23行: 创建log目录
代码24~26行: 创建log文件
代码31~40: 初始化log参数
代码44~50行: 加载配置文件
代码54~67行: 初始化系统和运行参数
源文件代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-'
import os, sys
import datetime
import logging
import pytest
import coloredlogs
from libs.utilis.config_tool import*
def pytest_addoption(parser):
parser.addoption(
"--system_conf", action="store", default="system",
help="config file option: default is system => config_system.yml"
)
def setup_logging(level=logging.INFO, log_folder=None, filename=None):
# create base folder
if os.path.exists(log_folder) is not True:
os.makedirs(log_folder) # create report folder
log_filename = None
if filename is not None and log_folder is not None:
log_filename = log_folder + os.sep + filename
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
log_format = '%(asctime)s - %(levelname)5s - %(lineno)4s - %(filename)18s - %(message)10s'
logging.basicConfig(filename=log_filename, level=level, format=log_format)
if log_filename is not None:
console = logging.StreamHandler(stream=sys.stdout)
console.setLevel(logging.getLogger().level)
console.setFormatter(logging.Formatter(log_format))
logging.getLogger().addHandler(console)
coloredlogs.install(level=level, fmt=log_format, milliseconds=True)
logging.info('')
@pytest.fixture(scope='session')
def yml_conf(request):
logging.info('*** start fixture: yml_conf')
filename = request.config.getoption("--system_conf")
conf = ConfigTool(filename)
conf.load_resource_file()
logging.info(" filename= %s" % filename)
yield conf
@pytest.fixture(scope='session')
def setup_context(yml_conf):
log_folder = yml_conf.get_ctc()['logfolder']
log_folder = '../log/%s' % log_folder
log_folder = log_folder +os.sep + ('%s' % datetime.datetime.now().strftime('%Y%m%d-%H%M%S'))
setup_logging(logging.DEBUG, log_folder, yml_conf.get_ctc()['logfile'])
logging.info('*** start fixture: context ***')
logging.info('init context object.')
logging.info('config file: %s' % yml_conf.filename)
logging.info('ctc: %s' % yml_conf.get_ctc())
logging.info('ctc uart: %s' % yml_conf.get_ctc_uart())
logging.info('gps uart: %s' % yml_conf.get_gps_uart())
logging.info('relay uart: %s' % yml_conf.get_relay_uart())
logging.info('\r\n')
2.3 编写case文件
代码第14~18行: case头部分,用于初始化case运行的环境
代码第21~28行: case尾部分,运行完成case,释放资源
代码31~33: 初始化case运行参数的函数
代码38 ~ 72: 编写一个case类,实现了3个case
源代码文件:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @describe : it is only a sourcecode case
# @Time : 2019/11/21 20:21
# @Author : mingfei.tang
import sys
import pytest
import time
import allure
import logging
@pytest.fixture(scope="module", autouse=True)
def mod_header(request):
logging.info('\r\n')
logging.info('=========================== start mod_header =================================')
logging.info('module name: %s' % request.module.__name__)
logging.info('=========================== End of mod_header ================================')
@pytest.fixture(scope="function", autouse=True)
def func_header(request):
logging.info('\r\n')
logging.info('=========================== start func_header =================================')
logging.info('case name: %s' % request.function.__name__)
logging.info('run time: %s' % time.asctime())
logging.info('=========================== End of func_header ===============================')
logging.info('\r\n')
@pytest.fixture(params=[2])
def init_data(request):
return request.param
@allure.feature('sourcecode testcase ')
@pytest.mark.usefixtures('setup_context')
class TestClass:
@classmethod
def setup_class(cls):
logging.info('setup class')
@classmethod
def teardown_class(cls):
logging.info("teardown class")
@allure.severity('blocker')
@allure.feature('test_demo_case_0')
@pytest.mark.usefixtures('yml_conf')
def test_demo_case_0(self):
init_data = 0
logging.info('test_demo_case_0')
logging.debug('test_data: %s' % init_data)
assert init_data == 0
@allure.severity('blocker')
@allure.feature('test_demo_case_1')
@pytest.mark.usefixtures('yml_conf')
def test_demo_case_1(self):
init_data = 14
logging.info('test_demo_case_1')
logging.debug('test_data: %s' % init_data)
assert init_data == 14
@allure.severity('blocker')
@allure.feature('test_demo_case_2')
def test_demo_case_2(self):
init_data = 15
time.sleep(10)
logging.info('test_demo_case_2')
logging.debug('test_data: %s' % init_data)
assert init_data == 15
2.4 运行脚本文件: run.common.sh
代码16~22行: 检查pytest是否已经运行,如果运行则kill pytest
代码24~28行: 运行case
代码30~34: 使用allure生成report
代码36~39: 使用pytest生成report
源代码文件:
#!/usr/bin/env bash
# -*- coding: utf-8 -*-
# @Time : 2019/11/27 09:51
# @File : run.common.sh
# @Author : mingfei.tang
###############################
ConfigFile_yml=''
module_name=''
key_words=''
report_dir=''
#DATE="`date +%Y-%m-%d_%H-%M-%S`"
#REPORT_HTML_DIR="report/${report_dir}/${DATE}/html"
#REPORT_PYTEST_DIR="report/${report_dir}/${DATE}/pyhtml"
function kill_pytest()
{
if [ "${OS}" == "Windows_NT" ]
then
taskkill.exe -F -IM pytest.exe -T
fi
}
function run_test_case()
{
mkdir -p "${REPORT_PYTEST_DIR}" 2> /dev/null
pytest --capture=no --color=yes --verbose --alluredir="${REPORT_PYTEST_DIR}" --system_conf="conf/${ConfigFile_yml}.yml" -k "${key_words}" "test_case/${module_name}.py"
}
function run_allure_html_report()
{
mkdir -p "${REPORT_HTML_DIR}"
allure generate "${REPORT_PYTEST_DIR}" -o "${REPORT_HTML_DIR}"
}
function run_pytest_html_report()
{
pytest --alluredir="${REPORT_PYTEST_DIR}" --system_conf="conf/${ConfigFile_yml}.yml" -k "${key_words}" "test_case/${module_name}.py" --html="${REPORT_PYTEST_DIR}"/report.html --self-contained-html
}
function run_generate_report()
{
if [ "${OS}" == "Windows_NT" ]
then
run_allure_html_report
else
run_pytest_html_report
fi
}
3 运行case
3.1 执行case
在代码所在的目录中运行git bash
在该目录下执行:
./run_test_01_demo.sh
运行log如下:
运行完成后,生成report:
3.2 查看report
1) 总的报告结果
2) 单个case的运行时间
3)查看case的执行log