框架作者没有对pytest格式的测试用例做一个参数化的官方demo,这里补充一下.
如果要对断言做关联参数化,框架本身是不支持的,需要改源码:这里-优化断言正则匹配
部分
只参数化请求报文内容的话,则不需要修改源码.
使用环境变量.env
-作用域: 整个项目
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).parent.parent))
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from httprunner import Parameters
class TestCaseBattle(HttpRunner):
config = (
Config("battle: login")
.base_url("http://xxx.xx.xx.225:12356")
.verify(False)
)
teststeps = [
Step(
RunRequest("post form data")
.with_variables(**{"res":"please select One Equipment"})
.post("/login")
.with_data({"username":"${ENV(username)}","password":"${ENV(password)}"}) #调用env变量
.validate()
.assert_equal("status_code", 200)
.assert_regex_match("body", "${res}")
),
]
if __name__ == "__main__":
TestCaseBattle().test_start()
在config使用variables关键字
和在step使用with_variables
定义变量
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).parent.parent))
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from httprunner import Parameters
class TestCaseBattle(HttpRunner):
config = (
Config("battle: login")
.variables(
**{
"username": "gsky",
"password": "gsky",
}
)
.base_url("http://xxx.xx.xx.225:12356")
.verify(False)
)
teststeps = [
Step(
RunRequest("post form data")
.with_variables(**{"res":"please select One Equipment"})
.post("/login")
.with_data({"username":"$username","password":"$password"})
.validate()
.assert_equal("status_code", 200)
.assert_regex_match("body", "${res}")
),
]
if __name__ == "__main__":
TestCaseBattle().test_start()
使用Parameters参数化
独立参数
代码
@pytest.mark.parametrize(
"param", Parameters({"equipmentid": ["10001","10002","10003"]})
)
def test_start(self, param):
super().test_start(param)
关联参数-直接枚举
代码
@pytest.mark.parametrize(
"param",
Parameters(
{"enemyid-equipmentid-res": [
["20001", "10002","You win Level 1"],
["20001", "10001","Your and your enemy all dead!!!"],
["", "10002","Error 9904: Your kill yourself!!"],
["20004", "","Error 9905: Your fight your enemy by nothing!And you are died!"],
]}
),
)
def test_start(self,param):
super().test_start(param)
关联参数-生成笛卡尔积
各个参数会以笛卡尔积的方式组合.
下面会组合成四条测试用例
['gsky','gsky'],['gsky','gsky123'],['gsky123','gsky],['gsky123','gsky123]
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).parent.parent))
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from httprunner import Parameters
class TestCaseBattle(HttpRunner):
@pytest.mark.parametrize(
"param",
Parameters(
{"username":["gsky","gsky123"],"password":["gsky","gsky123"]}
),
)
def test_start(self,param):
super().test_start(param)
config = (
Config("battle: login")
.base_url("http://xxx.xx.xx.225:12356")
.verify(False)
)
teststeps = [
Step(
RunRequest("post form data")
.with_variables(**{"res":"please select One Equipment"})
.post("/login")
.with_data({"username":"$username","password":"$password"})
.validate()
.assert_equal("status_code", 200)
.assert_regex_match("body", "${res}")
),
]
if __name__ == "__main__":
TestCaseBattle().test_start()
使用csv文件枚举所有场景
使用csv文件参数化.对于项目来说,应该支持:
- 在测试用例里写入csv文件绝对路径
- 从环境变量里,拿到csv文件的绝对路径,测试用例里只写环境变量的
name
最好的实践是第二种方式.
不建议在测试文件中使用csv文件的相对路径,使用相对路径的话修改起来非常麻烦, 因此,框架改动后也就不支持这种方式.
对于csv文件参数化,需要修改源码.
loader.py
中,csv_file = os.path.join(project_meta.RootDir, *csv_file.split("/"))
注释掉,改为从.env文件中获取csv文件路径
# make compatible with Windows/Linux
# csv_file = os.path.join(project_meta.RootDir, *csv_file.split("/"))
try:
temp = os.getenv(csv_file)
except IOError:
print('.evn文件中的环境变量account_path不存在')
else:
csv_file = temp
csv文件:
代码
import sys
from pathlib import Path
import pytest
sys.path.insert(0, str(Path(__file__).parent.parent))
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
from httprunner import Parameters
class TestCaseBattle(HttpRunner):
@pytest.mark.parametrize(
"param",
Parameters(
{"username-password-res":"${P(battle_cases/account.csv)}"}
),
)
def test_start(self,param):
super().test_start(param)
config = (
Config("battle: login")
.base_url("http://xx.xx.xx.xx:12356")
.verify(False)
)
teststeps = [
Step(
RunRequest("post form data")
.post("/login")
.with_data({"username":"$username","password":"$password"})
.validate()
.assert_equal("status_code", 200)
.assert_regex_match("body", "${res}")
),
]
if __name__ == "__main__":
TestCaseBattle().test_start()
执行结果