httprunner3.x 测试用例关联及运行

测试用例关联

hhttprunner中不仅有hook机制,还有用例关联操作,引用内置的RunTestCase类,主要用于在测试步骤中引用其他测试用例

        Step(
            RunTestCase('request login functions')
            .call(TestCaseLogin)
            .export(*['token'])

RunTestCase(name):初始化,可自定义的name名称,必填项

.call(类名): 指定引用的测试用例类

.export(变量):指定从引用的测试用例中提取所需的关联变量

 

# -*-coding:utf-8 -*-
# ** createDate: 2021/3/23 14:22
# ** scriptFile: testcase_student_login_test.py
 
 
from httprunner import (HttpRunner, Config, Step, RunRequest)
 
 
class TestCaseLogin(HttpRunner):
 
    config = (
        Config("login")
        .base_url("${ENV(HOSTURL)}")
        .verify(False)
    )
    teststeps = [
        Step(
            RunRequest('login')
            .with_variables(**{'token_length': 32, 'status_code': 201, 'status': 1})
            .post('/client/user/auth')
            .with_headers(**{"Content-Type": "application/json"})
            .with_json({"scenario": "client", "company_id": '${ENV(COMPANYID)}', "user_name": "${ENV(USERNAME)}", 
                        "password": "${ENV(PASSWORD)}", "device_type": "1", "device": ""})
            .extract()
            .with_jmespath("body.data.token", "token")
            .validate()
            .assert_equal('status_code', '$status_code', '断言失败')
        )
    ]
 
 
if __name__ == '__main__':
    TestCaseLogin().test_start() 

 

如果想要下个用例能引用到token值,我们必须要先在当前用例使用 .with_jmespath(token)提取关联值

# -*-coding:utf-8 -*-
# ** createDate: 2021/3/26 17:44
# ** scriptFile: testcase_student_visit_index_test.py
 
from .testcase_student_login_test import TestCaseLogin
from httprunner import (HttpRunner, Config, Step, RunRequest, RunTestCase)
 
 
class TestCaseIndex(HttpRunner):
 
    config = (
        Config("index")
        .base_url("${ENV(HOSTURL)}")
        .verify(False)
    )
    teststeps = [
        Step(
            RunTestCase('request login functions')
            .call(TestCaseLogin)
            .export(*['token'])
        ),
        Step(
            RunRequest('index')
            .with_variables(**{'status_code': 200, 'status': 1})
            .get('/client/user/index')
            .with_headers(**{"Content-Type": "application/json", 'token': '$token'})
            .validate()
            .assert_equal('body.status', '$status', '断言失败')
        )
    ]
 
 
if __name__ == '__main__':
    TestCaseLogin().test_start()

 

  1. 首先引入httprunner中的RunTestCase()类
  2. 其次testcase_student_visit_index_test.py文件中引入了 testcase_student_login_test.py文件中的 TestCaseLogin类
  3. 最后进行RunTestCase(name)、.call(引入关联的类名)、.export(*['关联变量'])

 

直接命令行输入 hrun 
testcase_student_visit_index_test.py -v 显示运行结果:

F:\TESTING\apiWebStudent\demo\testcases>hrun testcase_student_visit_index_test.py -v
2021-03-27 15:56:18.300 | INFO     | httprunner.make:__make:512 - make path: F:\TESTING\apiWebStudent\demo\testcases\testcase_student_visit_index_test.py
2021-03-27 15:56:18.302 | INFO     | httprunner.make:format_pytest_with_black:170 - format pytest cases with black ...
No Path provided. Nothing to do �
2021-03-27 15:56:18.558 | INFO     | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.1.4
================================================================================= test session starts =================================================================================
rootdir: F:\TESTING\apiWebStudent\demo\testcases
plugins: allure-pytest-2.8.24, cov-2.8.1, emoji-0.2.0, forked-1.3.0, html-2.1.1, metadata-1.11.0, rerunfailures-9.1.1, xdist-2.1.0
collected 2 items                                                                                                                                                                      
 
testcase_student_visit_index_test.py::TestCaseLogin::test_start PASSED                                                                                                           [ 50%]
testcase_student_visit_index_test.py::TestCaseIndex::test_start PASSED                                                                                                           [100%]
 
================================================================================== 2 passed in 0.64s ==================================================================================
2021-03-27 15:56:18.8982021-03-27 15:56:18.9012021-03-27 15:56:18.9022021-03-27 15:56:18.9022021-03-27 15:56:18.9032021-03-27 15:56:18.9072021-03-27 15:56:18.9092021-03-27 15:56:19.046
2021-03-27 15:56:19.0462021-03-27 15:56:19.0472021-03-27 15:56:19.0492021-03-27 15:56:19.0492021-03-27 15:56:19.0502021-03-27 15:56:19.0512021-03-27 15:56:19.0512021-03-27 15:56:19.052
2021-03-27 15:56:19.0592021-03-27 15:56:19.0602021-03-27 15:56:19.0612021-03-27 15:56:19.2042021-03-27 15:56:19.2052021-03-27 15:56:19.2062021-03-27 15:56:19.2072021-03-27 15:56:19.208
2021-03-27 15:56:19.2082021-03-27 15:56:19.2092021-03-27 15:56:19.2092021-03-27 15:56:19.2102021-03-27 15:56:19.2102021-03-27 15:56:19.2112021-03-27 15:56:19.4042021-03-27 15:56:19.405
2021-03-27 15:56:19.4062021-03-27 15:56:19.4082021-03-27 15:56:19.4092021-03-27 15:56:19.4102021-03-27 15:56:19.4102021-03-27 15:56:19.411

 

注意点:

  • 如果前置用例没有使用 .with_jmespath(token)准备好参数,后置用例引用会报错
  • 如果前置用例使用的数据驱动,后置用例也要把前置的数据驱动方法拿过来使用,不然用例关联是会失败的

 

示例部分代码如下:

# -*-coding:utf-8 -*-
# ** createDate: 2021/3/23 14:22
# ** scriptFile: testcase_student_login_test.py
"""
注释信息:部分代码
"""
 
import pytest
from httprunner import (HttpRunner, Config, Step, RunRequest, Parameters)
 
 
class TestCaseLogin(HttpRunner):
 
    @pytest.mark.parametrize('param', Parameters({'device_type': [1]}))
    def test_start(self, param):
        super().test_start(param)
 
    config = (
        Config("login")
        .base_url("${ENV(HOSTURL)}")
        .verify(False)
    )
 
......

 

前置测试用例代码中做了数据驱动,如果要实施用例关联,当前用例必须也要加上前置这段数据驱动代码:

# -*-coding:utf-8 -*-
# ** createDate: 2021/3/26 17:44
# ** scriptFile: testcase_student_visit_index_test.py
"""
注释信息:部分代码
"""
 
import pytest
from .testcase_student_login_test import TestCaseLogin
from httprunner import (HttpRunner, Config, Step, RunRequest, RunTestCase, Parameters)
 
 
class TestCaseIndex(HttpRunner):
 
    @pytest.mark.parametrize('param', Parameters({'device_type': [1]}))
    def test_start(self, param):
        super().test_start(param)
 
    config = (
        Config("index")
        .base_url("${ENV(HOSTURL)}")
        .verify(False)
    )
......

 

针对上述代码中后置用例为什么也要加数据驱动,个人认为有两种原因:

  1. 因为引用了前置用例,而前置用例又需要传入必填参数,所以后置用例引入包后必须也要加上,相当于函数的位置参数传参一样,必传项,不传就报错一样。
  2. 前置用例中的test_start()方法我们重写了,重写的test_start()方法,增加了一个位置参数,后置引用时,会先运行前置,所以必须要增加一段和前置一样的数据驱动方法
#  数据驱动方法
 
    @pytest.mark.parametrize('param', Parameters({'device_type': [1]}))
    def test_start(self, param):
        super().test_start(param)

 

所以建议,如果没有数据驱动的前置用例可以直接引用给后置用例进行关联,如果有数据驱动的,还是推荐在debugtalk.py中编写hook函数使用。针对用例还是尽可能地做到独立运行,独立运行,独立运行,不然你会吃亏的。

 

运行测试用例

注意:hrun是httprunner run的缩写;你也可以直接使用 httprunner run 命令

#        指定路径文件运行
 
hrun testcases/testcase_student_visit_index_test.py -v
 
#        指定路径运行项目中所有的用例
 
hrun testcases
 
#        指定多个文件路径执行
 
hrun testcases/testcase_student_visit_index_test.py -v testcases/testcase_student_login_test.py
 

 

hrun只是包装了pytest框架,可以直接使用pytest命令运行,把hrun改成pytest即可

注意点:pytest命令只针对.py文件使用,yaml/json文件的得用hrun

#        运行项目中所有测试用例
 
pytest testcases
 
#        指定多个文件路径执行
 
pytest testcases/testcase_student_visit_index_test.py -v testcases/testcase_student_login_test.py
 
#        查看所有hrun中包装了的pytest命令;只展示部分
 
F:\TESTING\apiWebStudent\demo>hrun -h
usage: hrun [options] [file_or_dir] [file_or_dir] [...]
 
positional arguments:
  file_or_dir
 
general:
  -k EXPRESSION         only run tests which match the given substring expression. An expression is a python evaluatable expression where all names are substring-matched against test
                        names and their parent classes. Example: -k 'test_method or test_other' matches all test functions and classes whose name contains 'test_method' or
                        'test_other', while -k 'not test_method' matches those that don't contain 'test_method' in their names. -k 'not test_method and not test_other' will eliminate
                        the matches. Additionally keywords are matched to classes and functions containing extra names in their 'extra_keyword_matches' set, as well as functions which
                        have names assigned directly to them. The matching is case-insensitive.
  -m MARKEXPR           only run tests matching given mark expression. example: -m 'mark1 and not mark2'.
  --markers             show markers (builtin, plugin and per-project ones).
  -x, --exitfirst       exit instantly on first error or failed test.
  --maxfail=num         exit after first num failures or errors.
  --strict-markers, --strict
                        markers not registered in the `markers` section of the configuration file raise errors.
  -c file               load configuration from `file` instead of trying to locate one of the implicit configuration files.
  --continue-on-collection-errors
                        Force test execution even if collection errors occur.
  --rootdir=ROOTDIR     Define root directory for tests. Can be relative path: 'root_dir', './root_dir', 'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with
                        variables: '$HOME/root_dir'.
  --fixtures, --funcargs
                        show available fixtures, sorted by plugin appearance (fixtures with leading '_' are only shown with '-v')
  --fixtures-per-test   show fixtures per test
  ......

 

以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,评论区留言会及时修正发布,谢谢!

 

未完,待续…

一直都在努力,希望您也是!

 

转载请附带原文链接 ( https://www.cnblogs.com/lifeng0402/articles/15186008.html ),否则追究法律责任,谢谢!


 

 

 

posted @ 2021-08-25 17:12  一名小测试  阅读(369)  评论(0)    收藏  举报