From 8cd6f4bd30de39eb2daae48e85134a524c3d8c99 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Wed, 17 Jun 2020 16:59:22 +0800 Subject: [PATCH] Deployed d0e4df6 with MkDocs version: 1.1.2 --- 404.html | 24 + CHANGELOG/index.html | 24 + dev/models/index.html | 24 + index.html | 24 + installation/index.html | 24 + quickstart/index.html | 337 +---------- search/search_index.json | 2 +- sitemap.xml | 22 +- sitemap.xml.gz | Bin 198 -> 200 bytes sponsors/index.html | 28 +- user/gen_tests/index.html | 24 + user/run_testcase/index.html | 1003 ++++++++++++++++++++++++++++++++ user/scaffold/index.html | 24 + user/testing_report/index.html | 585 +++++++++++++++++++ user/write_testcase/index.html | 117 +++- 15 files changed, 1937 insertions(+), 325 deletions(-) create mode 100644 user/run_testcase/index.html create mode 100644 user/testing_report/index.html diff --git a/404.html b/404.html index 033933b2..42d519ae 100644 --- a/404.html +++ b/404.html @@ -268,6 +268,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/CHANGELOG/index.html b/CHANGELOG/index.html index 881d2cbd..9bbb3814 100644 --- a/CHANGELOG/index.html +++ b/CHANGELOG/index.html @@ -273,6 +273,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/dev/models/index.html b/dev/models/index.html index 78761c80..40a5a516 100644 --- a/dev/models/index.html +++ b/dev/models/index.html @@ -273,6 +273,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/index.html b/index.html index c66364bc..485628a9 100644 --- a/index.html +++ b/index.html @@ -329,6 +329,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/installation/index.html b/installation/index.html index f4ffd6cc..1358e0d5 100644 --- a/installation/index.html +++ b/installation/index.html @@ -318,6 +318,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/quickstart/index.html b/quickstart/index.html index 5bf9b3ea..b509c748 100644 --- a/quickstart/index.html +++ b/quickstart/index.html @@ -273,6 +273,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + @@ -319,65 +343,6 @@ - - - @@ -394,260 +359,6 @@

    Quick Start

    First of all, remember HttpRunner is a simple yet powerful HTTP(S) testing framework. This document will help you to learn HttpRunner in 10 minutes.

    -

    Write the first test case

    -

    Open your favorite text editor and you can write test cases like this.

    -
    - test:
    -    name: get token
    -    request:
    -        url: http://127.0.0.1:5000/api/get-token
    -        method: POST
    -        headers:
    -            user_agent: iOS/10.3
    -            device_sn: 9TN6O2Bn1vzfybF
    -            os_platform: ios
    -            app_version: 2.8.6
    -        json:
    -            sign: 19067cf712265eb5426db8d3664026c1ccea02b9
    -
    -- test:
    -    name: create user which does not exist
    -    request:
    -        url: http://127.0.0.1:5000/api/users/1000
    -        method: POST
    -        headers:
    -            device_sn: 9TN6O2Bn1vzfybF
    -            token: F8prvGryC5beBr4g
    -        json:
    -            name: "user1"
    -            password: "123456"
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 201}
    -        - {"check": "content.success", "comparator": "eq", "expect": true}
    -
    - - -

    As you see, each API request is described in a test block. And in the request field, it describes the detail of HTTP request, includes url, method, headers and data, which are in line with the captured traffic.

    -

    You may wonder why we use the json field other than data. That's because the post data is in JSON format, when we use json to indicate the post data, we do not have to specify Content-Type to be application/json in request headers or dump data before request.

    -

    Have you recalled some familiar scenes?

    -

    Yes! That's what we did in requests.request! Since HttpRunner takes full reuse of Requests, it inherits all powerful features of Requests, and we can handle HTTP request as the way we do before.

    -

    Run test cases

    -

    Suppose the test case file is named as quickstart-demo-rev-0.yml and is located in examples folder, then we can run it in this way.

    -
    ate examples/demo-rev-0.yml
    -Running tests...
    -----------------------------------------------------------------------
    - get token ... INFO:root: Start to POST http://127.0.0.1:5000/api/get-token
    -INFO:root: status_code: 200, response_time: 48 ms, response_length: 46 bytes
    -OK (0.049669)s
    - create user which does not exist ... INFO:root: Start to POST http://127.0.0.1:5000/api/users/1000
    -ERROR:root: Failed to POST http://127.0.0.1:5000/api/users/1000! exception msg: 403 Client Error: FORBIDDEN for url: http://127.0.0.1:5000/api/users/1000
    -ERROR (0.006471)s
    -----------------------------------------------------------------------
    -Ran 2 tests in 0.056s
    -
    -FAILED
    - (Errors=1)
    -
    - - -

    Oops! The second test case failed with 403 status code.

    -

    That is because we request with the same data as we captured in Charles Proxy, while the token is generated dynamically, thus the recorded data can not be be used twice directly.

    -

    Optimize test case: correlation

    -

    To fix this problem, we should correlate token field in the second API test case, which is also called correlation.

    -
    - test:
    -    name: get token
    -    request:
    -        url: http://127.0.0.1:5000/api/get-token
    -        method: POST
    -        headers:
    -            user_agent: iOS/10.3
    -            device_sn: 9TN6O2Bn1vzfybF
    -            os_platform: ios
    -            app_version: 2.8.6
    -        json:
    -            sign: 19067cf712265eb5426db8d3664026c1ccea02b9
    -    extract:
    -        - token: content.token
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 200}
    -        - {"check": "content.token", "comparator": "len_eq", "expect": 16}
    -
    -- test:
    -    name: create user which does not exist
    -    request:
    -        url: http://127.0.0.1:5000/api/users/1000
    -        method: POST
    -        headers:
    -            device_sn: 9TN6O2Bn1vzfybF
    -            token: $token
    -        json:
    -            name: "user1"
    -            password: "123456"
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 201}
    -        - {"check": "content.success", "comparator": "eq", "expect": true}
    -
    - - -

    As you see, the token field is no longer hardcoded, instead it is extracted from the first API request with extract mechanism. In the meanwhile, it is assigned to token variable, which can be referenced by the subsequent API requests.

    -

    Now we save the test cases to quickstart-demo-rev-1.yml and rerun it, and we will find that both API requests to be successful.

    -

    Optimize test case: parameterization

    -

    Let's look back to our test set quickstart-demo-rev-1.yml, and we can see the device_sn field is still hardcoded. This may be quite different from the actual scenarios.

    -

    In actual scenarios, each user's device_sn is different, so we should parameterize the request parameters, which is also called parameterization. In the meanwhile, the sign field is calculated with other header fields, thus it may change significantly if any header field changes slightly.

    -

    However, the test cases are only YAML documents, it is impossible to generate parameters dynamically in such text. Fortunately, we can combine Python scripts with YAML/JSON test cases in HttpRunner.

    -

    To achieve this goal, we can utilize debugtalk.py plugin and variables mechanisms.

    -

    To be specific, we can create a Python file (examples/debugtalk.py) and implement the related algorithm in it. The debugtalk.py file can not only be located beside YAML/JSON testcase file, but also can be in any upward recursive folder. Since we want debugtalk.py to be importable, we should put a __init__.py in its folder to make it as a Python module.

    -
    import hashlib
    -import hmac
    -import random
    -import string
    -
    -SECRET_KEY = "DebugTalk"
    -
    -def get_sign(*args):
    -    content = ''.join(args).encode('ascii')
    -    sign_key = SECRET_KEY.encode('ascii')
    -    sign = hmac.new(sign_key, content, hashlib.sha1).hexdigest()
    -    return sign
    -
    -def gen_random_string(str_len):
    -    random_char_list = []
    -    for _ in range(str_len):
    -        random_char = random.choice(string.ascii_letters + string.digits)
    -        random_char_list.append(random_char)
    -
    -    random_string = ''.join(random_char_list)
    -    return random_string
    -
    - - -

    And then, we can revise our demo test case and reference the functions. Suppose the revised file named quickstart-demo-rev-2.yml.

    -
    - test:
    -    name: get token
    -    variables:
    -        - user_agent: 'iOS/10.3'
    -        - device_sn: ${gen_random_string(15)}
    -        - os_platform: 'ios'
    -        - app_version: '2.8.6'
    -    request:
    -        url: http://127.0.0.1:5000/api/get-token
    -        method: POST
    -        headers:
    -            user_agent: $user_agent
    -            device_sn: $device_sn
    -            os_platform: $os_platform
    -            app_version: $app_version
    -        json:
    -            sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)}
    -    extract:
    -        - token: content.token
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 200}
    -        - {"check": "content.token", "comparator": "len_eq", "expect": 16}
    -
    -- test:
    -    name: create user which does not exist
    -    request:
    -        url: http://127.0.0.1:5000/api/users/1000
    -        method: POST
    -        headers:
    -            device_sn: $device_sn
    -            token: $token
    -        json:
    -            name: "user1"
    -            password: "123456"
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 201}
    -        - {"check": "content.success", "comparator": "eq", "expect": true}
    -
    - - -

    In this revised test case, variable reference and function invoke mechanisms are both used.

    -

    To make fields like device_sn can be used more than once, we bind values to variables in variables block. When we bind variables, we can not only bind exact value to a variable name, but also can call a function and bind the evaluated value to it.

    -

    When we want to reference a variable in the test case, we can do this with a escape character $. For example, $user_agent will not be taken as a normal string, and HttpRunner will consider it as a variable named user_agent, search and return its binding value.

    -

    When we want to reference a function, we shall use another escape character ${}. Any content in ${} will be considered as function calling, so we should guarantee that we call functions in the right way. At the same time, variables can also be referenced as parameters of function.

    -

    Optimize test case: overall config block

    -

    There is still one issue unsolved.

    -

    The device_sn field is defined in the first API test case, thus it may be impossible to reference it in other test cases. Context separation is a well-designed mechanism, and we should obey this good practice.

    -

    To handle this case, overall config block is supported in HttpRunner. If we define variables or import functions in config block, these variables and functions will become global and can be referenced in the whole test set.

    -
    # examples/quickstart-demo-rev-3.yml
    -- config:
    -    name: "smoketest for CRUD users."
    -    variables:
    -        - device_sn: ${gen_random_string(15)}
    -    request:
    -        base_url: http://127.0.0.1:5000
    -        headers:
    -            device_sn: $device_sn
    -
    -- test:
    -    name: get token
    -    variables:
    -        - user_agent: 'iOS/10.3'
    -        - os_platform: 'ios'
    -        - app_version: '2.8.6'
    -    request:
    -        url: /api/get-token
    -        method: POST
    -        headers:
    -            user_agent: $user_agent
    -            os_platform: $os_platform
    -            app_version: $app_version
    -        json:
    -            sign: ${get_sign($user_agent, $device_sn, $os_platform, $app_version)}
    -    extract:
    -        - token: content.token
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 200}
    -        - {"check": "content.token", "comparator": "len_eq", "expect": 16}
    -
    -- test:
    -    name: create user which does not exist
    -    request:
    -        url: /api/users/1000
    -        method: POST
    -        headers:
    -            token: $token
    -        json:
    -            name: "user1"
    -            password: "123456"
    -    validate:
    -        - {"check": "status_code", "comparator": "eq", "expect": 201}
    -        - {"check": "content.success", "comparator": "eq", "expect": true}
    -
    - - -

    As you see, we define variables in config block. Also, we can set base_url in config block, thereby we can specify relative path in each API request url. Besides, we can also set common fields in config request, such as device_sn in headers.

    -

    Until now, the test cases are finished and each detail is handled properly.

    -

    Run test cases and generate report

    -

    Finally, let's run test set quickstart-demo-rev-3.yml once more.

    -
    $ ate examples/quickstart-demo-rev-4.yml
    -Running tests...
    -----------------------------------------------------------------------
    - get token ... INFO:root: Start to POST http://127.0.0.1:5000/api/get-token
    -INFO:root: status_code: 200, response_time: 33 ms, response_length: 46 bytes
    -OK (0.037027)s
    - create user which does not exist ... INFO:root: Start to POST http://127.0.0.1:5000/api/users/1000
    -INFO:root: status_code: 201, response_time: 15 ms, response_length: 54 bytes
    -OK (0.016414)s
    -----------------------------------------------------------------------
    -Ran 2 tests in 0.054s
    -OK
    -
    -Generating HTML reports...
    -Template is not specified, load default template instead.
    -Reports generated: /Users/Leo/MyProjects/HttpRunner/reports/quickstart-demo-rev-0/2017-08-01-16-51-51.html
    -
    - - -

    Great! The test case runs successfully and generates a HTML test report.

    -

    -

    Further more

    -

    This is just a starting point, see the advanced guide for the advanced features.

    - diff --git a/search/search_index.json b/search/search_index.json index 45a73284..0187985d 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"HttpRunner \u00b6 HttpRunner is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! \u2728 \ud83d\ude80 \u2728 This docs site is corresponding to the latest version 3.x , for 2.x you can reference archive link . Design Philosophy \u00b6 Convention over configuration ROI matters Embrace open source, leverage requests , pytest , pydantic , allure and locust . Key Features \u00b6 Inherit all powerful features of requests , just have fun to handle HTTP(S) in human way. Define testcase in YAML or JSON format, run with pytest in concise and elegant manner. Record and generate testcases with HAR support. Supports variables / extract / validate / hooks mechanisms to create extremely complex test scenarios. With debugtalk.py plugin, any function can be used in any part of your testcase. With jmespath , extract and validate json response has never been easier. With pytest , hundreds of plugins are readily available. With allure , test report can be pretty nice and powerful. With reuse of locust , you can run performance test without extra work. CLI command supported, perfect combination with CI/CD . Subscribe \u00b6 \u5173\u6ce8 HttpRunner \u7684\u5fae\u4fe1\u516c\u4f17\u53f7\uff0c\u7b2c\u4e00\u65f6\u95f4\u83b7\u5f97\u6700\u65b0\u8d44\u8baf\u3002","title":"Introduction"},{"location":"#httprunner","text":"HttpRunner is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! \u2728 \ud83d\ude80 \u2728 This docs site is corresponding to the latest version 3.x , for 2.x you can reference archive link .","title":"HttpRunner"},{"location":"#design-philosophy","text":"Convention over configuration ROI matters Embrace open source, leverage requests , pytest , pydantic , allure and locust .","title":"Design Philosophy"},{"location":"#key-features","text":"Inherit all powerful features of requests , just have fun to handle HTTP(S) in human way. Define testcase in YAML or JSON format, run with pytest in concise and elegant manner. Record and generate testcases with HAR support. Supports variables / extract / validate / hooks mechanisms to create extremely complex test scenarios. With debugtalk.py plugin, any function can be used in any part of your testcase. With jmespath , extract and validate json response has never been easier. With pytest , hundreds of plugins are readily available. With allure , test report can be pretty nice and powerful. With reuse of locust , you can run performance test without extra work. CLI command supported, perfect combination with CI/CD .","title":"Key Features"},{"location":"#subscribe","text":"\u5173\u6ce8 HttpRunner \u7684\u5fae\u4fe1\u516c\u4f17\u53f7\uff0c\u7b2c\u4e00\u65f6\u95f4\u83b7\u5f97\u6700\u65b0\u8d44\u8baf\u3002","title":"Subscribe"},{"location":"CHANGELOG/","text":"Release History \u00b6 3.0.13 (2020-06-15) \u00b6 Fixed fix: avoid '.csv' been converted to '_csv' fix: convert har to JSON format testcase fix: missing ${var} handling in overriding config variables fix: SyntaxError caused by quote in case of headers.\"Set-Cookie\" fix: FileExistsError when specified project name conflicts with existed file fix: testcase path handling error when path startswith \"./\" or \".\\\" 3.0.12 (2020-06-14) \u00b6 Fixed fix: compatibility with different path separators of Linux and Windows fix: IndexError in ensure_file_path_valid when file_path=os.getcwd() fix: ensure step referenced api, convert to v3 testcase fix: several other compatibility issues Changed change: skip reporting sentry for errors occurred in debugtalk.py 3.0.11 (2020-06-08) \u00b6 Changed change: override variables (1) testcase: session variables > step variables > config variables (2) testsuite: testcase variables > config variables (3) testsuite testcase variables > testcase config variables Fixed fix: incorrect summary success when testcase failed fix: reload to refresh previously loaded debugtalk module fix: escape $$ in variable value 3.0.10 (2020-06-07) \u00b6 Added feat: implement step setup/teardown hooks feat: support alter response in teardown hooks Fixed fix: ensure upload ready fix: add ExtendJSONEncoder to safely dump json data with python object, such as MultipartEncoder 3.0.9 (2020-06-07) \u00b6 Fixed fix: miss formatting referenced testcase fix: handle cases when parent directory name includes dot/hyphen/space Changed change: add export keyword in TStep to export session variables from referenced testcase change: rename TestCaseInOut field, config_vars and export_vars change: rename StepData field, export_vars change: add --tb=short for hrun command to use shorter traceback format by default change: search debugtalk.py upward recursively until system root dir 3.0.8 (2020-06-04) \u00b6 Added feat: add sentry sdk feat: extract session variable from referenced testcase step Fixed fix: missing request json fix: override testsuite/testcase config verify fix: only strip whitespaces and tabs, \\n\\r are left because they maybe used in changeset fix: log testcase duration before raise ValidationFailure Changed change: add httprunner version in generated pytest file 3.0.7 (2020-06-03) \u00b6 Added feat: make pytest files in chain style feat: hrun supports run pytest files feat: get raw testcase model from pytest file Fixed fix: convert jmespath.search result to int/float unintentionally fix: referenced testcase should not be run duplicately fix: requests.cookies.CookieConflictError, multiple cookies with name fix: missing exit code from pytest fix: skip invalid testcase/testsuite yaml/json file Changed change: har2case generate pytest file by default docs: update sponsor info 3.0.6 (2020-05-29) \u00b6 Added feat: make referenced testcase as pytest class Fixed fix: ensure converted python file in utf-8 encoding fix: duplicate running referenced testcase fix: ensure compatibility issues between testcase format v2 and v3 fix: ensure compatibility with deprecated cli args in v2, include --failfast/--report-file/--save-tests fix: UnicodeDecodeError when request body in protobuf Changed change: make allure-pytest , requests-toolbelt , filetype as optional dependencies change: move all unittests to tests folder change: save testcase log in PWD/logs/ directory 3.0.5 (2020-05-22) \u00b6 Added feat: each testcase has an unique id in uuid4 format feat: add default header HRUN-Request-ID for each testcase #721 feat: builtin allure report feat: dump log for each testcase Fixed fix: ensure referenced testcase share the same session Changed change: remove default added -s option for hrun 3.0.4 (2020-05-19) \u00b6 Added feat: make testsuite and run testsuite feat: testcase/testsuite config support getting variables by function feat: har2case with request cookies feat: log request/response headers and body with indent Fixed fix: extract response cookies fix: handle errors when no valid testcases generated Changed change: har2case do not ignore request headers, except for header startswith : 3.0.3 (2020-05-17) \u00b6 Fixed fix: compatibility with testcase file path includes dots, space and minus sign fix: testcase generator, validate content.xxx => body.xxx fix: scaffold for v3 3.0.2 (2020-05-16) \u00b6 Added feat: add make sub-command to generate python testcases from YAML/JSON feat: format generated python testcases with black test: add postman echo & httpbin as testcase examples Changed refactor all replace jsonschema validation with pydantic remove compatibility with testcase/testsuite format v1 replace unittest with pytest remove builtin html report, allure will be used with pytest later remove locust support temporarily update command line interface 3.0.1 (2020-03-24) \u00b6 Changed remove sentry sdk 3.0.0 (2020-03-10) \u00b6 Added feat: dump log for each testcase feat: add default header HRUN-Request-ID for each testcase #721 Changed remove support for Python 2.7 replace logging with loguru replace string format with f-string remove dependency colorama and colorlog generate reports/logs folder in current working directory remove cli --validate remove cli --pretty","title":"CHANGELOG"},{"location":"CHANGELOG/#release-history","text":"","title":"Release History"},{"location":"CHANGELOG/#3013-2020-06-15","text":"Fixed fix: avoid '.csv' been converted to '_csv' fix: convert har to JSON format testcase fix: missing ${var} handling in overriding config variables fix: SyntaxError caused by quote in case of headers.\"Set-Cookie\" fix: FileExistsError when specified project name conflicts with existed file fix: testcase path handling error when path startswith \"./\" or \".\\\"","title":"3.0.13 (2020-06-15)"},{"location":"CHANGELOG/#3012-2020-06-14","text":"Fixed fix: compatibility with different path separators of Linux and Windows fix: IndexError in ensure_file_path_valid when file_path=os.getcwd() fix: ensure step referenced api, convert to v3 testcase fix: several other compatibility issues Changed change: skip reporting sentry for errors occurred in debugtalk.py","title":"3.0.12 (2020-06-14)"},{"location":"CHANGELOG/#3011-2020-06-08","text":"Changed change: override variables (1) testcase: session variables > step variables > config variables (2) testsuite: testcase variables > config variables (3) testsuite testcase variables > testcase config variables Fixed fix: incorrect summary success when testcase failed fix: reload to refresh previously loaded debugtalk module fix: escape $$ in variable value","title":"3.0.11 (2020-06-08)"},{"location":"CHANGELOG/#3010-2020-06-07","text":"Added feat: implement step setup/teardown hooks feat: support alter response in teardown hooks Fixed fix: ensure upload ready fix: add ExtendJSONEncoder to safely dump json data with python object, such as MultipartEncoder","title":"3.0.10 (2020-06-07)"},{"location":"CHANGELOG/#309-2020-06-07","text":"Fixed fix: miss formatting referenced testcase fix: handle cases when parent directory name includes dot/hyphen/space Changed change: add export keyword in TStep to export session variables from referenced testcase change: rename TestCaseInOut field, config_vars and export_vars change: rename StepData field, export_vars change: add --tb=short for hrun command to use shorter traceback format by default change: search debugtalk.py upward recursively until system root dir","title":"3.0.9 (2020-06-07)"},{"location":"CHANGELOG/#308-2020-06-04","text":"Added feat: add sentry sdk feat: extract session variable from referenced testcase step Fixed fix: missing request json fix: override testsuite/testcase config verify fix: only strip whitespaces and tabs, \\n\\r are left because they maybe used in changeset fix: log testcase duration before raise ValidationFailure Changed change: add httprunner version in generated pytest file","title":"3.0.8 (2020-06-04)"},{"location":"CHANGELOG/#307-2020-06-03","text":"Added feat: make pytest files in chain style feat: hrun supports run pytest files feat: get raw testcase model from pytest file Fixed fix: convert jmespath.search result to int/float unintentionally fix: referenced testcase should not be run duplicately fix: requests.cookies.CookieConflictError, multiple cookies with name fix: missing exit code from pytest fix: skip invalid testcase/testsuite yaml/json file Changed change: har2case generate pytest file by default docs: update sponsor info","title":"3.0.7 (2020-06-03)"},{"location":"CHANGELOG/#306-2020-05-29","text":"Added feat: make referenced testcase as pytest class Fixed fix: ensure converted python file in utf-8 encoding fix: duplicate running referenced testcase fix: ensure compatibility issues between testcase format v2 and v3 fix: ensure compatibility with deprecated cli args in v2, include --failfast/--report-file/--save-tests fix: UnicodeDecodeError when request body in protobuf Changed change: make allure-pytest , requests-toolbelt , filetype as optional dependencies change: move all unittests to tests folder change: save testcase log in PWD/logs/ directory","title":"3.0.6 (2020-05-29)"},{"location":"CHANGELOG/#305-2020-05-22","text":"Added feat: each testcase has an unique id in uuid4 format feat: add default header HRUN-Request-ID for each testcase #721 feat: builtin allure report feat: dump log for each testcase Fixed fix: ensure referenced testcase share the same session Changed change: remove default added -s option for hrun","title":"3.0.5 (2020-05-22)"},{"location":"CHANGELOG/#304-2020-05-19","text":"Added feat: make testsuite and run testsuite feat: testcase/testsuite config support getting variables by function feat: har2case with request cookies feat: log request/response headers and body with indent Fixed fix: extract response cookies fix: handle errors when no valid testcases generated Changed change: har2case do not ignore request headers, except for header startswith :","title":"3.0.4 (2020-05-19)"},{"location":"CHANGELOG/#303-2020-05-17","text":"Fixed fix: compatibility with testcase file path includes dots, space and minus sign fix: testcase generator, validate content.xxx => body.xxx fix: scaffold for v3","title":"3.0.3 (2020-05-17)"},{"location":"CHANGELOG/#302-2020-05-16","text":"Added feat: add make sub-command to generate python testcases from YAML/JSON feat: format generated python testcases with black test: add postman echo & httpbin as testcase examples Changed refactor all replace jsonschema validation with pydantic remove compatibility with testcase/testsuite format v1 replace unittest with pytest remove builtin html report, allure will be used with pytest later remove locust support temporarily update command line interface","title":"3.0.2 (2020-05-16)"},{"location":"CHANGELOG/#301-2020-03-24","text":"Changed remove sentry sdk","title":"3.0.1 (2020-03-24)"},{"location":"CHANGELOG/#300-2020-03-10","text":"Added feat: dump log for each testcase feat: add default header HRUN-Request-ID for each testcase #721 Changed remove support for Python 2.7 replace logging with loguru replace string format with f-string remove dependency colorama and colorlog generate reports/logs folder in current working directory remove cli --validate remove cli --pretty","title":"3.0.0 (2020-03-10)"},{"location":"installation/","text":"HttpRunner is developed with Python, it supports Python 3.6+ and most operating systems. Combination of Python 3.6/3.7/3.8 and macOS/Linux/Windows are tested continuously on GitHub-Actions . Installation \u00b6 HttpRunner is available on PyPI and can be installed through pip . $ pip3 install httprunner If you want to keep up with the latest version, you can install with github repository url. $ pip3 install git+https://github.com/httprunner/httprunner.git@master If\b you have installed HttpRunner before and want to upgrade to the latest version, you can use the -U option. $ pip3 install -U httprunner $ pip3 install -U git+https://github.com/httprunner/httprunner.git@master Check Installation \u00b6 When HttpRunner is installed, 4 commands will be added in your system. httprunner : main command, used for all functions hrun : alias for httprunner run , used to run YAML/JSON/pytest testcases hmake : alias for httprunner make , used to convert YAML/JSON testcases to pytest files har2case : alias for httprunner har2case , used to convert HAR to YAML/JSON testcases To see HttpRunner version: $ httprunner -V # hrun -V 3.0.10 To see available options, run: $ httprunner -h usage: httprunner [-h] [-V] {run,startproject,har2case,make} ... One-stop solution for HTTP(S) testing. positional arguments: {run,startproject,har2case,make} sub-command help run Make HttpRunner testcases and run with pytest. startproject Create a new project with template structure. har2case Convert HAR(HTTP Archive) to YAML/JSON testcases for HttpRunner. make Convert YAML/JSON testcases to pytest cases. optional arguments: -h, --help show this help message and exit -V, --version show version","title":"Installation"},{"location":"installation/#installation","text":"HttpRunner is available on PyPI and can be installed through pip . $ pip3 install httprunner If you want to keep up with the latest version, you can install with github repository url. $ pip3 install git+https://github.com/httprunner/httprunner.git@master If\b you have installed HttpRunner before and want to upgrade to the latest version, you can use the -U option. $ pip3 install -U httprunner $ pip3 install -U git+https://github.com/httprunner/httprunner.git@master","title":"Installation"},{"location":"installation/#check-installation","text":"When HttpRunner is installed, 4 commands will be added in your system. httprunner : main command, used for all functions hrun : alias for httprunner run , used to run YAML/JSON/pytest testcases hmake : alias for httprunner make , used to convert YAML/JSON testcases to pytest files har2case : alias for httprunner har2case , used to convert HAR to YAML/JSON testcases To see HttpRunner version: $ httprunner -V # hrun -V 3.0.10 To see available options, run: $ httprunner -h usage: httprunner [-h] [-V] {run,startproject,har2case,make} ... One-stop solution for HTTP(S) testing. positional arguments: {run,startproject,har2case,make} sub-command help run Make HttpRunner testcases and run with pytest. startproject Create a new project with template structure. har2case Convert HAR(HTTP Archive) to YAML/JSON testcases for HttpRunner. make Convert YAML/JSON testcases to pytest cases. optional arguments: -h, --help show this help message and exit -V, --version show version","title":"Check Installation"},{"location":"quickstart/","text":"Quick Start \u00b6 First of all, remember HttpRunner is a simple yet powerful HTTP(S) testing framework. This document will help you to learn HttpRunner in 10 minutes. Write the first test case \u00b6 Open your favorite text editor and you can write test cases like this. - test : name : get token request : url : http://127.0.0.1:5000/api/get-token method : POST headers : user_agent : iOS/10.3 device_sn : 9TN6O2Bn1vzfybF os_platform : ios app_version : 2.8.6 json : sign : 19067cf712265eb5426db8d3664026c1ccea02b9 - test : name : create user which does not exist request : url : http://127.0.0.1:5000/api/users/1000 method : POST headers : device_sn : 9TN6O2Bn1vzfybF token : F8prvGryC5beBr4g json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } As you see, each API request is described in a test block. And in the request field, it describes the detail of HTTP request, includes url, method, headers and data, which are in line with the captured traffic. You may wonder why we use the json field other than data . That's because the post data is in JSON format, when we use json to indicate the post data, we do not have to specify Content-Type to be application/json in request headers or dump data before request. Have you recalled some familiar scenes? Yes! That's what we did in requests.request ! Since HttpRunner takes full reuse of Requests , it inherits all powerful features of Requests , and we can handle HTTP request as the way we do before. Run test cases \u00b6 Suppose the test case file is named as quickstart-demo-rev-0.yml and is located in examples folder, then we can run it in this way. ate examples/demo-rev-0.yml Running tests... ---------------------------------------------------------------------- get token ... INFO:root: Start to POST http://127.0.0.1:5000/api/get-token INFO:root: status_code: 200, response_time: 48 ms, response_length: 46 bytes OK (0.049669)s create user which does not exist ... INFO:root: Start to POST http://127.0.0.1:5000/api/users/1000 ERROR:root: Failed to POST http://127.0.0.1:5000/api/users/1000! exception msg: 403 Client Error: FORBIDDEN for url: http://127.0.0.1:5000/api/users/1000 ERROR (0.006471)s ---------------------------------------------------------------------- Ran 2 tests in 0.056s FAILED (Errors=1) Oops! The second test case failed with 403 status code. That is because we request with the same data as we captured in Charles Proxy , while the token is generated dynamically, thus the recorded data can not be be used twice directly. Optimize test case: correlation \u00b6 To fix this problem, we should correlate token field in the second API test case, which is also called correlation . - test : name : get token request : url : http://127.0.0.1:5000/api/get-token method : POST headers : user_agent : iOS/10.3 device_sn : 9TN6O2Bn1vzfybF os_platform : ios app_version : 2.8.6 json : sign : 19067cf712265eb5426db8d3664026c1ccea02b9 extract : - token : content.token validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 200 } - { \"check\" : \"content.token\" , \"comparator\" : \"len_eq\" , \"expect\" : 16 } - test : name : create user which does not exist request : url : http://127.0.0.1:5000/api/users/1000 method : POST headers : device_sn : 9TN6O2Bn1vzfybF token : $token json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } As you see, the token field is no longer hardcoded, instead it is extracted from the first API request with extract mechanism. In the meanwhile, it is assigned to token variable, which can be referenced by the subsequent API requests. Now we save the test cases to quickstart-demo-rev-1.yml and rerun it, and we will find that both API requests to be successful. Optimize test case: parameterization \u00b6 Let's look back to our test set quickstart-demo-rev-1.yml , and we can see the device_sn field is still hardcoded. This may be quite different from the actual scenarios. In actual scenarios, each user's device_sn is different, so we should parameterize the request parameters, which is also called parameterization . In the meanwhile, the sign field is calculated with other header fields, thus it may change significantly if any header field changes slightly. However, the test cases are only YAML documents, it is impossible to generate parameters dynamically in such text. Fortunately, we can combine Python scripts with YAML/JSON test cases in HttpRunner . To achieve this goal, we can utilize debugtalk.py plugin and variables mechanisms. To be specific, we can create a Python file ( examples/debugtalk.py ) and implement the related algorithm in it. The debugtalk.py file can not only be located beside YAML/JSON testcase file, but also can be in any upward recursive folder. Since we want debugtalk.py to be importable, we should put a __init__.py in its folder to make it as a Python module. import hashlib import hmac import random import string SECRET_KEY = \"DebugTalk\" def get_sign ( * args ): content = '' . join ( args ) . encode ( 'ascii' ) sign_key = SECRET_KEY . encode ( 'ascii' ) sign = hmac . new ( sign_key , content , hashlib . sha1 ) . hexdigest () return sign def gen_random_string ( str_len ): random_char_list = [] for _ in range ( str_len ): random_char = random . choice ( string . ascii_letters + string . digits ) random_char_list . append ( random_char ) random_string = '' . join ( random_char_list ) return random_string And then, we can revise our demo test case and reference the functions. Suppose the revised file named quickstart-demo-rev-2.yml . - test : name : get token variables : - user_agent : 'iOS/10.3' - device_sn : ${gen_random_string(15)} - os_platform : 'ios' - app_version : '2.8.6' request : url : http://127.0.0.1:5000/api/get-token method : POST headers : user_agent : $user_agent device_sn : $device_sn os_platform : $os_platform app_version : $app_version json : sign : ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} extract : - token : content.token validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 200 } - { \"check\" : \"content.token\" , \"comparator\" : \"len_eq\" , \"expect\" : 16 } - test : name : create user which does not exist request : url : http://127.0.0.1:5000/api/users/1000 method : POST headers : device_sn : $device_sn token : $token json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } In this revised test case, variable reference and function invoke mechanisms are both used. To make fields like device_sn can be used more than once, we bind values to variables in variables block. When we bind variables, we can not only bind exact value to a variable name, but also can call a function and bind the evaluated value to it. When we want to reference a variable in the test case, we can do this with a escape character $ . For example, $user_agent will not be taken as a normal string, and HttpRunner will consider it as a variable named user_agent , search and return its binding value. When we want to reference a function, we shall use another escape character ${} . Any content in ${} will be considered as function calling, so we should guarantee that we call functions in the right way. At the same time, variables can also be referenced as parameters of function. Optimize test case: overall config block \u00b6 There is still one issue unsolved. The device_sn field is defined in the first API test case, thus it may be impossible to reference it in other test cases. Context separation is a well-designed mechanism, and we should obey this good practice. To handle this case, overall config block is supported in HttpRunner . If we define variables or import functions in config block, these variables and functions will become global and can be referenced in the whole test set. # examples/quickstart-demo-rev-3.yml - config : name : \"smoketest for CRUD users.\" variables : - device_sn : ${gen_random_string(15)} request : base_url : http://127.0.0.1:5000 headers : device_sn : $device_sn - test : name : get token variables : - user_agent : 'iOS/10.3' - os_platform : 'ios' - app_version : '2.8.6' request : url : /api/get-token method : POST headers : user_agent : $user_agent os_platform : $os_platform app_version : $app_version json : sign : ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} extract : - token : content.token validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 200 } - { \"check\" : \"content.token\" , \"comparator\" : \"len_eq\" , \"expect\" : 16 } - test : name : create user which does not exist request : url : /api/users/1000 method : POST headers : token : $token json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } As you see, we define variables in config block. Also, we can set base_url in config block, thereby we can specify relative path in each API request url. Besides, we can also set common fields in config request , such as device_sn in headers. Until now, the test cases are finished and each detail is handled properly. Run test cases and generate report \u00b6 Finally, let's run test set quickstart-demo-rev-3.yml once more. $ ate examples/quickstart-demo-rev-4.yml Running tests... ---------------------------------------------------------------------- get token ... INFO:root: Start to POST http://127.0.0.1:5000/api/get-token INFO:root: status_code: 200, response_time: 33 ms, response_length: 46 bytes OK (0.037027)s create user which does not exist ... INFO:root: Start to POST http://127.0.0.1:5000/api/users/1000 INFO:root: status_code: 201, response_time: 15 ms, response_length: 54 bytes OK (0.016414)s ---------------------------------------------------------------------- Ran 2 tests in 0.054s OK Generating HTML reports... Template is not specified, load default template instead. Reports generated: /Users/Leo/MyProjects/HttpRunner/reports/quickstart-demo-rev-0/2017-08-01-16-51-51.html Great! The test case runs successfully and generates a HTML test report. Further more \u00b6 This is just a starting point, see the advanced guide for the advanced features. templating data extraction and validation comparator","title":"Quick Start"},{"location":"quickstart/#quick-start","text":"First of all, remember HttpRunner is a simple yet powerful HTTP(S) testing framework. This document will help you to learn HttpRunner in 10 minutes.","title":"Quick Start"},{"location":"quickstart/#write-the-first-test-case","text":"Open your favorite text editor and you can write test cases like this. - test : name : get token request : url : http://127.0.0.1:5000/api/get-token method : POST headers : user_agent : iOS/10.3 device_sn : 9TN6O2Bn1vzfybF os_platform : ios app_version : 2.8.6 json : sign : 19067cf712265eb5426db8d3664026c1ccea02b9 - test : name : create user which does not exist request : url : http://127.0.0.1:5000/api/users/1000 method : POST headers : device_sn : 9TN6O2Bn1vzfybF token : F8prvGryC5beBr4g json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } As you see, each API request is described in a test block. And in the request field, it describes the detail of HTTP request, includes url, method, headers and data, which are in line with the captured traffic. You may wonder why we use the json field other than data . That's because the post data is in JSON format, when we use json to indicate the post data, we do not have to specify Content-Type to be application/json in request headers or dump data before request. Have you recalled some familiar scenes? Yes! That's what we did in requests.request ! Since HttpRunner takes full reuse of Requests , it inherits all powerful features of Requests , and we can handle HTTP request as the way we do before.","title":"Write the first test case"},{"location":"quickstart/#run-test-cases","text":"Suppose the test case file is named as quickstart-demo-rev-0.yml and is located in examples folder, then we can run it in this way. ate examples/demo-rev-0.yml Running tests... ---------------------------------------------------------------------- get token ... INFO:root: Start to POST http://127.0.0.1:5000/api/get-token INFO:root: status_code: 200, response_time: 48 ms, response_length: 46 bytes OK (0.049669)s create user which does not exist ... INFO:root: Start to POST http://127.0.0.1:5000/api/users/1000 ERROR:root: Failed to POST http://127.0.0.1:5000/api/users/1000! exception msg: 403 Client Error: FORBIDDEN for url: http://127.0.0.1:5000/api/users/1000 ERROR (0.006471)s ---------------------------------------------------------------------- Ran 2 tests in 0.056s FAILED (Errors=1) Oops! The second test case failed with 403 status code. That is because we request with the same data as we captured in Charles Proxy , while the token is generated dynamically, thus the recorded data can not be be used twice directly.","title":"Run test cases"},{"location":"quickstart/#optimize-test-case-correlation","text":"To fix this problem, we should correlate token field in the second API test case, which is also called correlation . - test : name : get token request : url : http://127.0.0.1:5000/api/get-token method : POST headers : user_agent : iOS/10.3 device_sn : 9TN6O2Bn1vzfybF os_platform : ios app_version : 2.8.6 json : sign : 19067cf712265eb5426db8d3664026c1ccea02b9 extract : - token : content.token validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 200 } - { \"check\" : \"content.token\" , \"comparator\" : \"len_eq\" , \"expect\" : 16 } - test : name : create user which does not exist request : url : http://127.0.0.1:5000/api/users/1000 method : POST headers : device_sn : 9TN6O2Bn1vzfybF token : $token json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } As you see, the token field is no longer hardcoded, instead it is extracted from the first API request with extract mechanism. In the meanwhile, it is assigned to token variable, which can be referenced by the subsequent API requests. Now we save the test cases to quickstart-demo-rev-1.yml and rerun it, and we will find that both API requests to be successful.","title":"Optimize test case: correlation"},{"location":"quickstart/#optimize-test-case-parameterization","text":"Let's look back to our test set quickstart-demo-rev-1.yml , and we can see the device_sn field is still hardcoded. This may be quite different from the actual scenarios. In actual scenarios, each user's device_sn is different, so we should parameterize the request parameters, which is also called parameterization . In the meanwhile, the sign field is calculated with other header fields, thus it may change significantly if any header field changes slightly. However, the test cases are only YAML documents, it is impossible to generate parameters dynamically in such text. Fortunately, we can combine Python scripts with YAML/JSON test cases in HttpRunner . To achieve this goal, we can utilize debugtalk.py plugin and variables mechanisms. To be specific, we can create a Python file ( examples/debugtalk.py ) and implement the related algorithm in it. The debugtalk.py file can not only be located beside YAML/JSON testcase file, but also can be in any upward recursive folder. Since we want debugtalk.py to be importable, we should put a __init__.py in its folder to make it as a Python module. import hashlib import hmac import random import string SECRET_KEY = \"DebugTalk\" def get_sign ( * args ): content = '' . join ( args ) . encode ( 'ascii' ) sign_key = SECRET_KEY . encode ( 'ascii' ) sign = hmac . new ( sign_key , content , hashlib . sha1 ) . hexdigest () return sign def gen_random_string ( str_len ): random_char_list = [] for _ in range ( str_len ): random_char = random . choice ( string . ascii_letters + string . digits ) random_char_list . append ( random_char ) random_string = '' . join ( random_char_list ) return random_string And then, we can revise our demo test case and reference the functions. Suppose the revised file named quickstart-demo-rev-2.yml . - test : name : get token variables : - user_agent : 'iOS/10.3' - device_sn : ${gen_random_string(15)} - os_platform : 'ios' - app_version : '2.8.6' request : url : http://127.0.0.1:5000/api/get-token method : POST headers : user_agent : $user_agent device_sn : $device_sn os_platform : $os_platform app_version : $app_version json : sign : ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} extract : - token : content.token validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 200 } - { \"check\" : \"content.token\" , \"comparator\" : \"len_eq\" , \"expect\" : 16 } - test : name : create user which does not exist request : url : http://127.0.0.1:5000/api/users/1000 method : POST headers : device_sn : $device_sn token : $token json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } In this revised test case, variable reference and function invoke mechanisms are both used. To make fields like device_sn can be used more than once, we bind values to variables in variables block. When we bind variables, we can not only bind exact value to a variable name, but also can call a function and bind the evaluated value to it. When we want to reference a variable in the test case, we can do this with a escape character $ . For example, $user_agent will not be taken as a normal string, and HttpRunner will consider it as a variable named user_agent , search and return its binding value. When we want to reference a function, we shall use another escape character ${} . Any content in ${} will be considered as function calling, so we should guarantee that we call functions in the right way. At the same time, variables can also be referenced as parameters of function.","title":"Optimize test case: parameterization"},{"location":"quickstart/#optimize-test-case-overall-config-block","text":"There is still one issue unsolved. The device_sn field is defined in the first API test case, thus it may be impossible to reference it in other test cases. Context separation is a well-designed mechanism, and we should obey this good practice. To handle this case, overall config block is supported in HttpRunner . If we define variables or import functions in config block, these variables and functions will become global and can be referenced in the whole test set. # examples/quickstart-demo-rev-3.yml - config : name : \"smoketest for CRUD users.\" variables : - device_sn : ${gen_random_string(15)} request : base_url : http://127.0.0.1:5000 headers : device_sn : $device_sn - test : name : get token variables : - user_agent : 'iOS/10.3' - os_platform : 'ios' - app_version : '2.8.6' request : url : /api/get-token method : POST headers : user_agent : $user_agent os_platform : $os_platform app_version : $app_version json : sign : ${get_sign($user_agent, $device_sn, $os_platform, $app_version)} extract : - token : content.token validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 200 } - { \"check\" : \"content.token\" , \"comparator\" : \"len_eq\" , \"expect\" : 16 } - test : name : create user which does not exist request : url : /api/users/1000 method : POST headers : token : $token json : name : \"user1\" password : \"123456\" validate : - { \"check\" : \"status_code\" , \"comparator\" : \"eq\" , \"expect\" : 201 } - { \"check\" : \"content.success\" , \"comparator\" : \"eq\" , \"expect\" : true } As you see, we define variables in config block. Also, we can set base_url in config block, thereby we can specify relative path in each API request url. Besides, we can also set common fields in config request , such as device_sn in headers. Until now, the test cases are finished and each detail is handled properly.","title":"Optimize test case: overall config block"},{"location":"quickstart/#run-test-cases-and-generate-report","text":"Finally, let's run test set quickstart-demo-rev-3.yml once more. $ ate examples/quickstart-demo-rev-4.yml Running tests... ---------------------------------------------------------------------- get token ... INFO:root: Start to POST http://127.0.0.1:5000/api/get-token INFO:root: status_code: 200, response_time: 33 ms, response_length: 46 bytes OK (0.037027)s create user which does not exist ... INFO:root: Start to POST http://127.0.0.1:5000/api/users/1000 INFO:root: status_code: 201, response_time: 15 ms, response_length: 54 bytes OK (0.016414)s ---------------------------------------------------------------------- Ran 2 tests in 0.054s OK Generating HTML reports... Template is not specified, load default template instead. Reports generated: /Users/Leo/MyProjects/HttpRunner/reports/quickstart-demo-rev-0/2017-08-01-16-51-51.html Great! The test case runs successfully and generates a HTML test report.","title":"Run test cases and generate report"},{"location":"quickstart/#further-more","text":"This is just a starting point, see the advanced guide for the advanced features. templating data extraction and validation comparator","title":"Further more"},{"location":"sponsors/","text":"\u8d5e\u52a9\u5546 \u00b6 \u611f\u8c22\u5404\u4f4d\u5bf9 HttpRunner \u7684\u8d5e\u52a9\u652f\u6301\uff01 \u91d1\u724c\u8d5e\u52a9\u5546\uff08Gold Sponsor\uff09 \u00b6 \u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f\u4e1a\u754c\u9886\u5148\u7684\u6d4b\u8bd5\u5f00\u53d1\u6280\u672f\u9ad8\u7aef\u6559\u80b2\u54c1\u724c\uff0c\u96b6\u5c5e\u4e8e\u6d4b\u5427\uff08\u5317\u4eac\uff09\u79d1\u6280\u6709\u9650\u516c\u53f8\u3002\u5b66\u9662\u8bfe\u7a0b\u5747\u7531 BAT \u4e00\u7ebf\u6d4b\u8bd5\u5927\u5496\u6267\u6559\uff0c\u63d0\u4f9b\u5b9e\u6218\u9a71\u52a8\u7684\u63a5\u53e3\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u79fb\u52a8\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u6027\u80fd\u6d4b\u8bd5\u3001\u6301\u7eed\u96c6\u6210\u4e0e DevOps \u7b49\u6280\u672f\u57f9\u8bad\uff0c\u4ee5\u53ca\u6d4b\u8bd5\u5f00\u53d1\u4f18\u79c0\u4eba\u624d\u5185\u63a8\u670d\u52a1\u3002 \u70b9\u51fb\u5b66\u4e60! \u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f HttpRunner \u7684\u9996\u5bb6\u91d1\u724c\u8d5e\u52a9\u5546\u3002 \u5f00\u6e90\u670d\u52a1\u8d5e\u52a9\u5546\uff08Open Source Sponsor\uff09 \u00b6 HttpRunner is in Sentry Sponsored plan. \u6210\u4e3a\u8d5e\u52a9\u5546 \u00b6 \u5982\u679c\u4f60\u6240\u5728\u7684\u516c\u53f8\u6216\u4e2a\u4eba\u4e5f\u60f3\u5bf9 HttpRunner \u8fdb\u884c\u8d5e\u52a9\uff0c\u53ef\u53c2\u8003\u5982\u4e0b\u65b9\u6848\uff0c\u5177\u4f53\u53ef\u8054\u7cfb \u9879\u76ee\u4f5c\u8005 \u3002 \u7b49\u7ea7 \u91d1\u724c\u8d5e\u52a9\u5546 \uff08Gold Sponsor\uff09 \u94f6\u724c\u8d5e\u52a9\u5546 \uff08Silver Sponsor\uff09 \u4e2a\u4eba\u8d5e\u8d4f \u91d1\u989d \uffe510000/\u5e74 \uffe55000/\u5e74 \u4efb\u610f \u6743\u76ca \u516c\u53f8 logo\uff08\u5927\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 150 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u516c\u53f8 logo\uff08\u4e2d\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 50 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u4e2a\u4eba ID \u548c\u94fe\u63a5\u5c55\u793a\u5728 sponsors.md","title":"Sponsors"},{"location":"sponsors/#_1","text":"\u611f\u8c22\u5404\u4f4d\u5bf9 HttpRunner \u7684\u8d5e\u52a9\u652f\u6301\uff01","title":"\u8d5e\u52a9\u5546"},{"location":"sponsors/#gold-sponsor","text":"\u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f\u4e1a\u754c\u9886\u5148\u7684\u6d4b\u8bd5\u5f00\u53d1\u6280\u672f\u9ad8\u7aef\u6559\u80b2\u54c1\u724c\uff0c\u96b6\u5c5e\u4e8e\u6d4b\u5427\uff08\u5317\u4eac\uff09\u79d1\u6280\u6709\u9650\u516c\u53f8\u3002\u5b66\u9662\u8bfe\u7a0b\u5747\u7531 BAT \u4e00\u7ebf\u6d4b\u8bd5\u5927\u5496\u6267\u6559\uff0c\u63d0\u4f9b\u5b9e\u6218\u9a71\u52a8\u7684\u63a5\u53e3\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u79fb\u52a8\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u6027\u80fd\u6d4b\u8bd5\u3001\u6301\u7eed\u96c6\u6210\u4e0e DevOps \u7b49\u6280\u672f\u57f9\u8bad\uff0c\u4ee5\u53ca\u6d4b\u8bd5\u5f00\u53d1\u4f18\u79c0\u4eba\u624d\u5185\u63a8\u670d\u52a1\u3002 \u70b9\u51fb\u5b66\u4e60! \u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f HttpRunner \u7684\u9996\u5bb6\u91d1\u724c\u8d5e\u52a9\u5546\u3002","title":"\u91d1\u724c\u8d5e\u52a9\u5546\uff08Gold Sponsor\uff09"},{"location":"sponsors/#open-source-sponsor","text":"HttpRunner is in Sentry Sponsored plan.","title":"\u5f00\u6e90\u670d\u52a1\u8d5e\u52a9\u5546\uff08Open Source Sponsor\uff09"},{"location":"sponsors/#_2","text":"\u5982\u679c\u4f60\u6240\u5728\u7684\u516c\u53f8\u6216\u4e2a\u4eba\u4e5f\u60f3\u5bf9 HttpRunner \u8fdb\u884c\u8d5e\u52a9\uff0c\u53ef\u53c2\u8003\u5982\u4e0b\u65b9\u6848\uff0c\u5177\u4f53\u53ef\u8054\u7cfb \u9879\u76ee\u4f5c\u8005 \u3002 \u7b49\u7ea7 \u91d1\u724c\u8d5e\u52a9\u5546 \uff08Gold Sponsor\uff09 \u94f6\u724c\u8d5e\u52a9\u5546 \uff08Silver Sponsor\uff09 \u4e2a\u4eba\u8d5e\u8d4f \u91d1\u989d \uffe510000/\u5e74 \uffe55000/\u5e74 \u4efb\u610f \u6743\u76ca \u516c\u53f8 logo\uff08\u5927\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 150 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u516c\u53f8 logo\uff08\u4e2d\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 50 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u4e2a\u4eba ID \u548c\u94fe\u63a5\u5c55\u793a\u5728 sponsors.md","title":"\u6210\u4e3a\u8d5e\u52a9\u5546"},{"location":"dev/models/","text":"Models \u00b6 HttpRunner v3.x uses pydantic to define models of testcase.","title":"Models"},{"location":"dev/models/#models","text":"HttpRunner v3.x uses pydantic to define models of testcase.","title":"Models"},{"location":"user/gen_tests/","text":"Record & Generate testcase \u00b6 capture HTTP request and response \u00b6 Before we write testcases, we should know the details of the API. It is a good choice to use a web debugging proxy tool like Charles Proxy to capture the HTTP traffic. For example, the image below illustrates post form data to postman-echo.com . export sessions to HAR file \u00b6 Then we can select captured request & response and export sessions to HTTP archive (.har) file. generate testcase with har2case \u00b6 When you get HAR file, you can use builtin command har2case to convert it to HttpRunner testcase. help \u00b6 $ har2case -h usage: har2case har2case [-h] [-2y] [-2j] [--filter FILTER] [--exclude EXCLUDE] [har_source_file] positional arguments: har_source_file Specify HAR source file optional arguments: -h, --help show this help message and exit -2y, --to-yml, --to-yaml Convert to YAML format, if not specified, convert to pytest format by default. -2j, --to-json Convert to JSON format, if not specified, convert to pytest format by default. --filter FILTER Specify filter keyword, only url include filter string will be converted. --exclude EXCLUDE Specify exclude keyword, url that includes exclude string will be ignored, multiple keywords can be joined with '|' generate testcase (pytest) \u00b6 Since HttpRunner 3.0.7 , har2case will convert HAR file to pytest by default, and it is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. $ har2case har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:08:01.191 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.har 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:08:01.194 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted. 2020-06-15 15:08:01.469 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py The generated pytest file is a standard Python file shown as below. # NOTE: Generated By HttpRunner v3.0.12 # FROM: har/postman-echo-post-form.har from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCasePostmanEchoPostForm ( HttpRunner ): config = Config ( \"testcase description\" ) . verify ( False ) teststeps = [ Step ( RunRequest ( \"/get\" ) . get ( \"https://postman-echo.com/get\" ) . with_params ( ** { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ) ), Step ( RunRequest ( \"/post\" ) . post ( \"https://postman-echo.com/post\" ) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . with_data ({ \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.data\" , \"\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/post\" ) ), ] if __name__ == \"__main__\" : TestCasePostmanEchoPostForm () . test_start () And it can be run with hrun command or the native pytest command. In fact, hrun is only a wrapper of pytest , thus the effect is basically the same. $ hrun har/postman_echo_post_form_test.py 2020-06-15 15:23:03.502 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:23:03.503 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... All done! \u2728 \ud83c\udf70 \u2728 1 file left unchanged. 2020-06-15 15:23:03.662 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.60s ======================================================================= $ pytest har/postman_echo_post_form_test.py ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ================================================================= 1 passed, 1 warning in 4.11s ================================================================== generate testcase (YAML/JSON) \u00b6 Of course, you can also generate former YAML/JSON testcase format. Just add -2y/--to-yml or -2j/--to-json argument to har2case . $ har2case har/postman-echo-post-form.har -2j 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:32:02.958 | INFO | httprunner.ext.har2case.utils:dump_json:122 - dump testcase to JSON format. 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.utils:dump_json:131 - Generate JSON testcase successfully: har/postman-echo-post-form.json 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: har/postman-echo-post-form.json { \"config\" : { \"name\" : \"testcase description\" , \"variables\" : {}, \"verify\" : false }, \"teststeps\" : [ { \"name\" : \"/get\" , \"request\" : { \"url\" : \"https://postman-echo.com/get\" , \"params\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }, \"method\" : \"GET\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ] } ] }, { \"name\" : \"/post\" , \"request\" : { \"url\" : \"https://postman-echo.com/post\" , \"method\" : \"POST\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"data\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.data\" , \"\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/post\" ] } ] } ] } The YAML/JSON testcase has the same info with pytest testcase, and you can run YAML/JSON testcase with hrun command. $ hrun har/postman-echo-post-form.json 2020-06-15 15:37:15.621 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:37:15.623 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.json 2020-06-15 15:37:15.625 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:37:15.625 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-15 15:37:15.962 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.03s =======================================================================","title":"Record & Generate testcase"},{"location":"user/gen_tests/#record-generate-testcase","text":"","title":"Record & Generate testcase"},{"location":"user/gen_tests/#capture-http-request-and-response","text":"Before we write testcases, we should know the details of the API. It is a good choice to use a web debugging proxy tool like Charles Proxy to capture the HTTP traffic. For example, the image below illustrates post form data to postman-echo.com .","title":"capture HTTP request and response"},{"location":"user/gen_tests/#export-sessions-to-har-file","text":"Then we can select captured request & response and export sessions to HTTP archive (.har) file.","title":"export sessions to HAR file"},{"location":"user/gen_tests/#generate-testcase-with-har2case","text":"When you get HAR file, you can use builtin command har2case to convert it to HttpRunner testcase.","title":"generate testcase with har2case"},{"location":"user/gen_tests/#help","text":"$ har2case -h usage: har2case har2case [-h] [-2y] [-2j] [--filter FILTER] [--exclude EXCLUDE] [har_source_file] positional arguments: har_source_file Specify HAR source file optional arguments: -h, --help show this help message and exit -2y, --to-yml, --to-yaml Convert to YAML format, if not specified, convert to pytest format by default. -2j, --to-json Convert to JSON format, if not specified, convert to pytest format by default. --filter FILTER Specify filter keyword, only url include filter string will be converted. --exclude EXCLUDE Specify exclude keyword, url that includes exclude string will be ignored, multiple keywords can be joined with '|'","title":"help"},{"location":"user/gen_tests/#generate-testcase-pytest","text":"Since HttpRunner 3.0.7 , har2case will convert HAR file to pytest by default, and it is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. $ har2case har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:08:01.191 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.har 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:08:01.194 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted. 2020-06-15 15:08:01.469 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py The generated pytest file is a standard Python file shown as below. # NOTE: Generated By HttpRunner v3.0.12 # FROM: har/postman-echo-post-form.har from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCasePostmanEchoPostForm ( HttpRunner ): config = Config ( \"testcase description\" ) . verify ( False ) teststeps = [ Step ( RunRequest ( \"/get\" ) . get ( \"https://postman-echo.com/get\" ) . with_params ( ** { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ) ), Step ( RunRequest ( \"/post\" ) . post ( \"https://postman-echo.com/post\" ) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . with_data ({ \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.data\" , \"\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/post\" ) ), ] if __name__ == \"__main__\" : TestCasePostmanEchoPostForm () . test_start () And it can be run with hrun command or the native pytest command. In fact, hrun is only a wrapper of pytest , thus the effect is basically the same. $ hrun har/postman_echo_post_form_test.py 2020-06-15 15:23:03.502 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:23:03.503 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... All done! \u2728 \ud83c\udf70 \u2728 1 file left unchanged. 2020-06-15 15:23:03.662 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.60s ======================================================================= $ pytest har/postman_echo_post_form_test.py ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ================================================================= 1 passed, 1 warning in 4.11s ==================================================================","title":"generate testcase (pytest)"},{"location":"user/gen_tests/#generate-testcase-yamljson","text":"Of course, you can also generate former YAML/JSON testcase format. Just add -2y/--to-yml or -2j/--to-json argument to har2case . $ har2case har/postman-echo-post-form.har -2j 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:32:02.958 | INFO | httprunner.ext.har2case.utils:dump_json:122 - dump testcase to JSON format. 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.utils:dump_json:131 - Generate JSON testcase successfully: har/postman-echo-post-form.json 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: har/postman-echo-post-form.json { \"config\" : { \"name\" : \"testcase description\" , \"variables\" : {}, \"verify\" : false }, \"teststeps\" : [ { \"name\" : \"/get\" , \"request\" : { \"url\" : \"https://postman-echo.com/get\" , \"params\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }, \"method\" : \"GET\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ] } ] }, { \"name\" : \"/post\" , \"request\" : { \"url\" : \"https://postman-echo.com/post\" , \"method\" : \"POST\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"data\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.data\" , \"\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/post\" ] } ] } ] } The YAML/JSON testcase has the same info with pytest testcase, and you can run YAML/JSON testcase with hrun command. $ hrun har/postman-echo-post-form.json 2020-06-15 15:37:15.621 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:37:15.623 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.json 2020-06-15 15:37:15.625 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:37:15.625 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-15 15:37:15.962 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.03s =======================================================================","title":"generate testcase (YAML/JSON)"},{"location":"user/scaffold/","text":"Scaffold \u00b6 If you want to create a new project, you can use the scaffold to startup quickly. help \u00b6 $ httprunner startproject -h usage: httprunner startproject [-h] [project_name] positional arguments: project_name Specify new project name. optional arguments: -h, --help show this help message and exit create new project \u00b6 The only argument you need to specify is the project name. $ httprunner startproject demo 2020-06-15 11:53:25.498 | INFO | httprunner.scaffold:create_scaffold:37 - Create new project: demo Project Root Dir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo created folder: demo created folder: demo/har created folder: demo/testcases created folder: demo/reports created file: demo/testcases/demo_testcase_request.yml created file: demo/testcases/demo_testcase_ref.yml created file: demo/debugtalk.py created file: demo/.env created file: demo/.gitignore $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files If you specify a project name that already exists, you will get a warning. $ httprunner startproject demo 2020-06-15 11:55:03.192 | WARNING | httprunner.scaffold:create_scaffold:32 - Project demo exists, please specify a new project name. $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files run scaffold project \u00b6 The scaffold project has several valid testcases, so you can run tests without any edit. $ hrun demo 2020-06-15 11:57:15.883 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/.env 2020-06-15 11:57:15.883 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 11:57:15.884 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 11:57:15.885 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref.yml 2020-06-15 11:57:15.898 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.899 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py 2020-06-15 11:57:15.900 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py 2020-06-15 11:57:15.911 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.912 | INFO | httprunner.make:__ensure_project_meta_files:128 - copy .env to /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/_env 2020-06-15 11:57:15.912 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py All done! \u2728 \ud83c\udf70 \u2728 2 files reformatted, 1 file left unchanged. 2020-06-15 11:57:16.299 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 2 items demo/testcases/demo_testcase_request_test.py . [ 50%] demo/testcases/demo_testcase_ref_test.py . [100%] ======================================================================= 2 passed in 6.87s =======================================================================","title":"Scaffold"},{"location":"user/scaffold/#scaffold","text":"If you want to create a new project, you can use the scaffold to startup quickly.","title":"Scaffold"},{"location":"user/scaffold/#help","text":"$ httprunner startproject -h usage: httprunner startproject [-h] [project_name] positional arguments: project_name Specify new project name. optional arguments: -h, --help show this help message and exit","title":"help"},{"location":"user/scaffold/#create-new-project","text":"The only argument you need to specify is the project name. $ httprunner startproject demo 2020-06-15 11:53:25.498 | INFO | httprunner.scaffold:create_scaffold:37 - Create new project: demo Project Root Dir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo created folder: demo created folder: demo/har created folder: demo/testcases created folder: demo/reports created file: demo/testcases/demo_testcase_request.yml created file: demo/testcases/demo_testcase_ref.yml created file: demo/debugtalk.py created file: demo/.env created file: demo/.gitignore $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files If you specify a project name that already exists, you will get a warning. $ httprunner startproject demo 2020-06-15 11:55:03.192 | WARNING | httprunner.scaffold:create_scaffold:32 - Project demo exists, please specify a new project name. $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files","title":"create new project"},{"location":"user/scaffold/#run-scaffold-project","text":"The scaffold project has several valid testcases, so you can run tests without any edit. $ hrun demo 2020-06-15 11:57:15.883 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/.env 2020-06-15 11:57:15.883 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 11:57:15.884 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 11:57:15.885 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref.yml 2020-06-15 11:57:15.898 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.899 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py 2020-06-15 11:57:15.900 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py 2020-06-15 11:57:15.911 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.912 | INFO | httprunner.make:__ensure_project_meta_files:128 - copy .env to /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/_env 2020-06-15 11:57:15.912 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py All done! \u2728 \ud83c\udf70 \u2728 2 files reformatted, 1 file left unchanged. 2020-06-15 11:57:16.299 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 2 items demo/testcases/demo_testcase_request_test.py . [ 50%] demo/testcases/demo_testcase_ref_test.py . [100%] ======================================================================= 2 passed in 6.87s =======================================================================","title":"run scaffold project"},{"location":"user/write_testcase/","text":"Write Testcase \u00b6 HttpRunner v3.x supports three testcase formats, pytest , YAML and JSON . It is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. The format relations are illustrated as below: record & generate testcase \u00b6 If the SUT (system under test) is ready, the most efficient way is to capture HTTP traffic first and then generate testcases with HAR file. Refer to Record & Generate testcase for more details. Based on the generated pytest testcase, you can then do some adjustment as needed, thus you need to know the details of testcase format. testcase structure \u00b6 Each testcase is a subclass of HttpRunner , and must have two class attributes: config and teststeps . config: configure testcase level settings, including base_url , verify , variables , export . teststeps: list of teststep ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Besides, variables / extract / validate / hooks mechanisms are supported to create extremely complex test scenarios. from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCaseRequestWithFunctions ( HttpRunner ): config = ( Config ( \"request methods testcase with functions\" ) . variables ( ** { \"foo1\" : \"config_bar1\" , \"foo2\" : \"config_bar2\" , \"expect_foo1\" : \"config_bar1\" , \"expect_foo2\" : \"config_bar2\" , } ) . base_url ( \"https://postman-echo.com\" ) . verify ( False ) . export ( * [ \"foo3\" ]) ) teststeps = [ Step ( RunRequest ( \"get with params\" ) . with_variables ( ** { \"foo1\" : \"bar11\" , \"foo2\" : \"bar21\" , \"sum_v\" : \"${sum_two(1, 2)}\" } ) . get ( \"/get\" ) . with_params ( ** { \"foo1\" : \"$foo1\" , \"foo2\" : \"$foo2\" , \"sum_v\" : \"$sum_v\" }) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" }) . extract () . with_jmespath ( \"body.args.foo2\" , \"foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.args.foo1\" , \"bar11\" ) . assert_equal ( \"body.args.sum_v\" , \"3\" ) . assert_equal ( \"body.args.foo2\" , \"bar21\" ) ), Step ( RunRequest ( \"post form data\" ) . with_variables ( ** { \"foo2\" : \"bar23\" }) . post ( \"/post\" ) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , } ) . with_data ( \"foo1=$foo1&foo2=$foo2&foo3=$foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.form.foo1\" , \"$expect_foo1\" ) . assert_equal ( \"body.form.foo2\" , \"bar23\" ) . assert_equal ( \"body.form.foo3\" , \"bar21\" ) ), ] if __name__ == \"__main__\" : TestCaseRequestWithFunctions () . test_start () chain call \u00b6 One of the most awesome features of HttpRunner v3.x is chain call , with which you do not need to remember any testcase format details and you can get intelligent completion when you write testcases in IDE. config \u00b6 Each testcase should have one config part, in which you can configure testcase level settings. name (required) \u00b6 Specify testcase name. This will be displayed in execution log and test report. base_url (optional) \u00b6 Specify common schema and host part of the SUT, e.g. https://postman-echo.com . If base_url is specified, url in teststep can only set relative path part. This is especially useful if you want to switch between different SUT environments. variables (optional) \u00b6 Specify common variables of testcase. Each teststep can reference config variable which is not set in step variables. In other words, step variables have higher priority than config variables. verify (optional) \u00b6 Specify whether to verify the server\u2019s TLS certificate. This is especially useful if we want to record HTTP traffic of testcase execution, because SSLError will be occurred if verify is not set or been set to True. SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')) export (optional) \u00b6 Specify the exported session variables of testcase. Consider each testcase as a black box, config variables is the input part, and config export is the output part. In particular, when a testcase is referenced in another testcase's step, and will be extracted some session variables to be used in subsequent teststeps, then the extracted session variables should be configured in config export part. teststeps \u00b6 Each testcase should have one or multiple ordered test steps ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Notice: The concept of API in HttpRunner v2.x has been deprecated for simplification. You can consider API as a testcase that has only one request step. RunRequest(name) \u00b6 RunRequest is used in a step to make request to API and do some extraction or validations for response. The argument name of RunRequest is used to specify teststep name, which will be displayed in execution log and test report. .with_variables \u00b6 Specify teststep variables. The variables of each step are independent, thus if you want to share variables in multiple steps, you should define variables in config variables. Besides, the step variables will override the ones that have the same name in config variables. .method(url) \u00b6 Specify HTTP method and the url of SUT. These are corresponding to method and url arguments of requests.request . If base_url is set in config, url can only set relative path part. .with_params \u00b6 Specify query string for the request url. This is corresponding to the params argument of requests.request . .with_headers \u00b6 Specify HTTP headers for the request. This is corresponding to the headers argument of requests.request . .with_cookies \u00b6 Specify HTTP request cookies. This is corresponding to the cookies argument of requests.request . .with_data \u00b6 Specify HTTP request body. This is corresponding to the data argument of requests.request . .with_json \u00b6 Specify HTTP request body in json. This is corresponding to the json argument of requests.request . extract \u00b6 .with_jmespath \u00b6 Extract JSON response body with jmespath . with_jmespath(jmes_path: Text, var_name: Text) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details var_name: the variable name that stores extracted value, it can be referenced by subsequent test steps validate \u00b6 .assert_XXX \u00b6 Extract JSON response body with jmespath and validate with expected value. assert_XXX(jmes_path: Text, expected_value: Any) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details expected_value: the specified expected value, variable or function reference can also be used here The image below shows HttpRunner builtin validators. RunTestCase(name) \u00b6 RunTestCase is used in a step to reference another testcase call. The argument name of RunTestCase is used to specify teststep name, which will be displayed in execution log and test report. .with_variables \u00b6 Same with RunRequest's .with_variables .","title":"Write Testcase"},{"location":"user/write_testcase/#write-testcase","text":"HttpRunner v3.x supports three testcase formats, pytest , YAML and JSON . It is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. The format relations are illustrated as below:","title":"Write Testcase"},{"location":"user/write_testcase/#record-generate-testcase","text":"If the SUT (system under test) is ready, the most efficient way is to capture HTTP traffic first and then generate testcases with HAR file. Refer to Record & Generate testcase for more details. Based on the generated pytest testcase, you can then do some adjustment as needed, thus you need to know the details of testcase format.","title":"record & generate testcase"},{"location":"user/write_testcase/#testcase-structure","text":"Each testcase is a subclass of HttpRunner , and must have two class attributes: config and teststeps . config: configure testcase level settings, including base_url , verify , variables , export . teststeps: list of teststep ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Besides, variables / extract / validate / hooks mechanisms are supported to create extremely complex test scenarios. from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCaseRequestWithFunctions ( HttpRunner ): config = ( Config ( \"request methods testcase with functions\" ) . variables ( ** { \"foo1\" : \"config_bar1\" , \"foo2\" : \"config_bar2\" , \"expect_foo1\" : \"config_bar1\" , \"expect_foo2\" : \"config_bar2\" , } ) . base_url ( \"https://postman-echo.com\" ) . verify ( False ) . export ( * [ \"foo3\" ]) ) teststeps = [ Step ( RunRequest ( \"get with params\" ) . with_variables ( ** { \"foo1\" : \"bar11\" , \"foo2\" : \"bar21\" , \"sum_v\" : \"${sum_two(1, 2)}\" } ) . get ( \"/get\" ) . with_params ( ** { \"foo1\" : \"$foo1\" , \"foo2\" : \"$foo2\" , \"sum_v\" : \"$sum_v\" }) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" }) . extract () . with_jmespath ( \"body.args.foo2\" , \"foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.args.foo1\" , \"bar11\" ) . assert_equal ( \"body.args.sum_v\" , \"3\" ) . assert_equal ( \"body.args.foo2\" , \"bar21\" ) ), Step ( RunRequest ( \"post form data\" ) . with_variables ( ** { \"foo2\" : \"bar23\" }) . post ( \"/post\" ) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , } ) . with_data ( \"foo1=$foo1&foo2=$foo2&foo3=$foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.form.foo1\" , \"$expect_foo1\" ) . assert_equal ( \"body.form.foo2\" , \"bar23\" ) . assert_equal ( \"body.form.foo3\" , \"bar21\" ) ), ] if __name__ == \"__main__\" : TestCaseRequestWithFunctions () . test_start ()","title":"testcase structure"},{"location":"user/write_testcase/#chain-call","text":"One of the most awesome features of HttpRunner v3.x is chain call , with which you do not need to remember any testcase format details and you can get intelligent completion when you write testcases in IDE.","title":"chain call"},{"location":"user/write_testcase/#config","text":"Each testcase should have one config part, in which you can configure testcase level settings.","title":"config"},{"location":"user/write_testcase/#name-required","text":"Specify testcase name. This will be displayed in execution log and test report.","title":"name (required)"},{"location":"user/write_testcase/#base_url-optional","text":"Specify common schema and host part of the SUT, e.g. https://postman-echo.com . If base_url is specified, url in teststep can only set relative path part. This is especially useful if you want to switch between different SUT environments.","title":"base_url (optional)"},{"location":"user/write_testcase/#variables-optional","text":"Specify common variables of testcase. Each teststep can reference config variable which is not set in step variables. In other words, step variables have higher priority than config variables.","title":"variables (optional)"},{"location":"user/write_testcase/#verify-optional","text":"Specify whether to verify the server\u2019s TLS certificate. This is especially useful if we want to record HTTP traffic of testcase execution, because SSLError will be occurred if verify is not set or been set to True. SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)'))","title":"verify (optional)"},{"location":"user/write_testcase/#export-optional","text":"Specify the exported session variables of testcase. Consider each testcase as a black box, config variables is the input part, and config export is the output part. In particular, when a testcase is referenced in another testcase's step, and will be extracted some session variables to be used in subsequent teststeps, then the extracted session variables should be configured in config export part.","title":"export (optional)"},{"location":"user/write_testcase/#teststeps","text":"Each testcase should have one or multiple ordered test steps ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Notice: The concept of API in HttpRunner v2.x has been deprecated for simplification. You can consider API as a testcase that has only one request step.","title":"teststeps"},{"location":"user/write_testcase/#runrequestname","text":"RunRequest is used in a step to make request to API and do some extraction or validations for response. The argument name of RunRequest is used to specify teststep name, which will be displayed in execution log and test report.","title":"RunRequest(name)"},{"location":"user/write_testcase/#with_variables","text":"Specify teststep variables. The variables of each step are independent, thus if you want to share variables in multiple steps, you should define variables in config variables. Besides, the step variables will override the ones that have the same name in config variables.","title":".with_variables"},{"location":"user/write_testcase/#methodurl","text":"Specify HTTP method and the url of SUT. These are corresponding to method and url arguments of requests.request . If base_url is set in config, url can only set relative path part.","title":".method(url)"},{"location":"user/write_testcase/#with_params","text":"Specify query string for the request url. This is corresponding to the params argument of requests.request .","title":".with_params"},{"location":"user/write_testcase/#with_headers","text":"Specify HTTP headers for the request. This is corresponding to the headers argument of requests.request .","title":".with_headers"},{"location":"user/write_testcase/#with_cookies","text":"Specify HTTP request cookies. This is corresponding to the cookies argument of requests.request .","title":".with_cookies"},{"location":"user/write_testcase/#with_data","text":"Specify HTTP request body. This is corresponding to the data argument of requests.request .","title":".with_data"},{"location":"user/write_testcase/#with_json","text":"Specify HTTP request body in json. This is corresponding to the json argument of requests.request .","title":".with_json"},{"location":"user/write_testcase/#extract","text":"","title":"extract"},{"location":"user/write_testcase/#with_jmespath","text":"Extract JSON response body with jmespath . with_jmespath(jmes_path: Text, var_name: Text) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details var_name: the variable name that stores extracted value, it can be referenced by subsequent test steps","title":".with_jmespath"},{"location":"user/write_testcase/#validate","text":"","title":"validate"},{"location":"user/write_testcase/#assert_xxx","text":"Extract JSON response body with jmespath and validate with expected value. assert_XXX(jmes_path: Text, expected_value: Any) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details expected_value: the specified expected value, variable or function reference can also be used here The image below shows HttpRunner builtin validators.","title":".assert_XXX"},{"location":"user/write_testcase/#runtestcasename","text":"RunTestCase is used in a step to reference another testcase call. The argument name of RunTestCase is used to specify teststep name, which will be displayed in execution log and test report.","title":"RunTestCase(name)"},{"location":"user/write_testcase/#with_variables_1","text":"Same with RunRequest's .with_variables .","title":".with_variables"}]} \ No newline at end of file +{"config":{"lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"HttpRunner \u00b6 HttpRunner is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! \u2728 \ud83d\ude80 \u2728 This docs site is corresponding to the latest version 3.x , for 2.x you can reference archive link . Design Philosophy \u00b6 Convention over configuration ROI matters Embrace open source, leverage requests , pytest , pydantic , allure and locust . Key Features \u00b6 Inherit all powerful features of requests , just have fun to handle HTTP(S) in human way. Define testcase in YAML or JSON format, run with pytest in concise and elegant manner. Record and generate testcases with HAR support. Supports variables / extract / validate / hooks mechanisms to create extremely complex test scenarios. With debugtalk.py plugin, any function can be used in any part of your testcase. With jmespath , extract and validate json response has never been easier. With pytest , hundreds of plugins are readily available. With allure , test report can be pretty nice and powerful. With reuse of locust , you can run performance test without extra work. CLI command supported, perfect combination with CI/CD . Subscribe \u00b6 \u5173\u6ce8 HttpRunner \u7684\u5fae\u4fe1\u516c\u4f17\u53f7\uff0c\u7b2c\u4e00\u65f6\u95f4\u83b7\u5f97\u6700\u65b0\u8d44\u8baf\u3002","title":"Introduction"},{"location":"#httprunner","text":"HttpRunner is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! \u2728 \ud83d\ude80 \u2728 This docs site is corresponding to the latest version 3.x , for 2.x you can reference archive link .","title":"HttpRunner"},{"location":"#design-philosophy","text":"Convention over configuration ROI matters Embrace open source, leverage requests , pytest , pydantic , allure and locust .","title":"Design Philosophy"},{"location":"#key-features","text":"Inherit all powerful features of requests , just have fun to handle HTTP(S) in human way. Define testcase in YAML or JSON format, run with pytest in concise and elegant manner. Record and generate testcases with HAR support. Supports variables / extract / validate / hooks mechanisms to create extremely complex test scenarios. With debugtalk.py plugin, any function can be used in any part of your testcase. With jmespath , extract and validate json response has never been easier. With pytest , hundreds of plugins are readily available. With allure , test report can be pretty nice and powerful. With reuse of locust , you can run performance test without extra work. CLI command supported, perfect combination with CI/CD .","title":"Key Features"},{"location":"#subscribe","text":"\u5173\u6ce8 HttpRunner \u7684\u5fae\u4fe1\u516c\u4f17\u53f7\uff0c\u7b2c\u4e00\u65f6\u95f4\u83b7\u5f97\u6700\u65b0\u8d44\u8baf\u3002","title":"Subscribe"},{"location":"CHANGELOG/","text":"Release History \u00b6 3.0.13 (2020-06-15) \u00b6 Fixed fix: avoid '.csv' been converted to '_csv' fix: convert har to JSON format testcase fix: missing ${var} handling in overriding config variables fix: SyntaxError caused by quote in case of headers.\"Set-Cookie\" fix: FileExistsError when specified project name conflicts with existed file fix: testcase path handling error when path startswith \"./\" or \".\\\" 3.0.12 (2020-06-14) \u00b6 Fixed fix: compatibility with different path separators of Linux and Windows fix: IndexError in ensure_file_path_valid when file_path=os.getcwd() fix: ensure step referenced api, convert to v3 testcase fix: several other compatibility issues Changed change: skip reporting sentry for errors occurred in debugtalk.py 3.0.11 (2020-06-08) \u00b6 Changed change: override variables (1) testcase: session variables > step variables > config variables (2) testsuite: testcase variables > config variables (3) testsuite testcase variables > testcase config variables Fixed fix: incorrect summary success when testcase failed fix: reload to refresh previously loaded debugtalk module fix: escape $$ in variable value 3.0.10 (2020-06-07) \u00b6 Added feat: implement step setup/teardown hooks feat: support alter response in teardown hooks Fixed fix: ensure upload ready fix: add ExtendJSONEncoder to safely dump json data with python object, such as MultipartEncoder 3.0.9 (2020-06-07) \u00b6 Fixed fix: miss formatting referenced testcase fix: handle cases when parent directory name includes dot/hyphen/space Changed change: add export keyword in TStep to export session variables from referenced testcase change: rename TestCaseInOut field, config_vars and export_vars change: rename StepData field, export_vars change: add --tb=short for hrun command to use shorter traceback format by default change: search debugtalk.py upward recursively until system root dir 3.0.8 (2020-06-04) \u00b6 Added feat: add sentry sdk feat: extract session variable from referenced testcase step Fixed fix: missing request json fix: override testsuite/testcase config verify fix: only strip whitespaces and tabs, \\n\\r are left because they maybe used in changeset fix: log testcase duration before raise ValidationFailure Changed change: add httprunner version in generated pytest file 3.0.7 (2020-06-03) \u00b6 Added feat: make pytest files in chain style feat: hrun supports run pytest files feat: get raw testcase model from pytest file Fixed fix: convert jmespath.search result to int/float unintentionally fix: referenced testcase should not be run duplicately fix: requests.cookies.CookieConflictError, multiple cookies with name fix: missing exit code from pytest fix: skip invalid testcase/testsuite yaml/json file Changed change: har2case generate pytest file by default docs: update sponsor info 3.0.6 (2020-05-29) \u00b6 Added feat: make referenced testcase as pytest class Fixed fix: ensure converted python file in utf-8 encoding fix: duplicate running referenced testcase fix: ensure compatibility issues between testcase format v2 and v3 fix: ensure compatibility with deprecated cli args in v2, include --failfast/--report-file/--save-tests fix: UnicodeDecodeError when request body in protobuf Changed change: make allure-pytest , requests-toolbelt , filetype as optional dependencies change: move all unittests to tests folder change: save testcase log in PWD/logs/ directory 3.0.5 (2020-05-22) \u00b6 Added feat: each testcase has an unique id in uuid4 format feat: add default header HRUN-Request-ID for each testcase #721 feat: builtin allure report feat: dump log for each testcase Fixed fix: ensure referenced testcase share the same session Changed change: remove default added -s option for hrun 3.0.4 (2020-05-19) \u00b6 Added feat: make testsuite and run testsuite feat: testcase/testsuite config support getting variables by function feat: har2case with request cookies feat: log request/response headers and body with indent Fixed fix: extract response cookies fix: handle errors when no valid testcases generated Changed change: har2case do not ignore request headers, except for header startswith : 3.0.3 (2020-05-17) \u00b6 Fixed fix: compatibility with testcase file path includes dots, space and minus sign fix: testcase generator, validate content.xxx => body.xxx fix: scaffold for v3 3.0.2 (2020-05-16) \u00b6 Added feat: add make sub-command to generate python testcases from YAML/JSON feat: format generated python testcases with black test: add postman echo & httpbin as testcase examples Changed refactor all replace jsonschema validation with pydantic remove compatibility with testcase/testsuite format v1 replace unittest with pytest remove builtin html report, allure will be used with pytest later remove locust support temporarily update command line interface 3.0.1 (2020-03-24) \u00b6 Changed remove sentry sdk 3.0.0 (2020-03-10) \u00b6 Added feat: dump log for each testcase feat: add default header HRUN-Request-ID for each testcase #721 Changed remove support for Python 2.7 replace logging with loguru replace string format with f-string remove dependency colorama and colorlog generate reports/logs folder in current working directory remove cli --validate remove cli --pretty","title":"CHANGELOG"},{"location":"CHANGELOG/#release-history","text":"","title":"Release History"},{"location":"CHANGELOG/#3013-2020-06-15","text":"Fixed fix: avoid '.csv' been converted to '_csv' fix: convert har to JSON format testcase fix: missing ${var} handling in overriding config variables fix: SyntaxError caused by quote in case of headers.\"Set-Cookie\" fix: FileExistsError when specified project name conflicts with existed file fix: testcase path handling error when path startswith \"./\" or \".\\\"","title":"3.0.13 (2020-06-15)"},{"location":"CHANGELOG/#3012-2020-06-14","text":"Fixed fix: compatibility with different path separators of Linux and Windows fix: IndexError in ensure_file_path_valid when file_path=os.getcwd() fix: ensure step referenced api, convert to v3 testcase fix: several other compatibility issues Changed change: skip reporting sentry for errors occurred in debugtalk.py","title":"3.0.12 (2020-06-14)"},{"location":"CHANGELOG/#3011-2020-06-08","text":"Changed change: override variables (1) testcase: session variables > step variables > config variables (2) testsuite: testcase variables > config variables (3) testsuite testcase variables > testcase config variables Fixed fix: incorrect summary success when testcase failed fix: reload to refresh previously loaded debugtalk module fix: escape $$ in variable value","title":"3.0.11 (2020-06-08)"},{"location":"CHANGELOG/#3010-2020-06-07","text":"Added feat: implement step setup/teardown hooks feat: support alter response in teardown hooks Fixed fix: ensure upload ready fix: add ExtendJSONEncoder to safely dump json data with python object, such as MultipartEncoder","title":"3.0.10 (2020-06-07)"},{"location":"CHANGELOG/#309-2020-06-07","text":"Fixed fix: miss formatting referenced testcase fix: handle cases when parent directory name includes dot/hyphen/space Changed change: add export keyword in TStep to export session variables from referenced testcase change: rename TestCaseInOut field, config_vars and export_vars change: rename StepData field, export_vars change: add --tb=short for hrun command to use shorter traceback format by default change: search debugtalk.py upward recursively until system root dir","title":"3.0.9 (2020-06-07)"},{"location":"CHANGELOG/#308-2020-06-04","text":"Added feat: add sentry sdk feat: extract session variable from referenced testcase step Fixed fix: missing request json fix: override testsuite/testcase config verify fix: only strip whitespaces and tabs, \\n\\r are left because they maybe used in changeset fix: log testcase duration before raise ValidationFailure Changed change: add httprunner version in generated pytest file","title":"3.0.8 (2020-06-04)"},{"location":"CHANGELOG/#307-2020-06-03","text":"Added feat: make pytest files in chain style feat: hrun supports run pytest files feat: get raw testcase model from pytest file Fixed fix: convert jmespath.search result to int/float unintentionally fix: referenced testcase should not be run duplicately fix: requests.cookies.CookieConflictError, multiple cookies with name fix: missing exit code from pytest fix: skip invalid testcase/testsuite yaml/json file Changed change: har2case generate pytest file by default docs: update sponsor info","title":"3.0.7 (2020-06-03)"},{"location":"CHANGELOG/#306-2020-05-29","text":"Added feat: make referenced testcase as pytest class Fixed fix: ensure converted python file in utf-8 encoding fix: duplicate running referenced testcase fix: ensure compatibility issues between testcase format v2 and v3 fix: ensure compatibility with deprecated cli args in v2, include --failfast/--report-file/--save-tests fix: UnicodeDecodeError when request body in protobuf Changed change: make allure-pytest , requests-toolbelt , filetype as optional dependencies change: move all unittests to tests folder change: save testcase log in PWD/logs/ directory","title":"3.0.6 (2020-05-29)"},{"location":"CHANGELOG/#305-2020-05-22","text":"Added feat: each testcase has an unique id in uuid4 format feat: add default header HRUN-Request-ID for each testcase #721 feat: builtin allure report feat: dump log for each testcase Fixed fix: ensure referenced testcase share the same session Changed change: remove default added -s option for hrun","title":"3.0.5 (2020-05-22)"},{"location":"CHANGELOG/#304-2020-05-19","text":"Added feat: make testsuite and run testsuite feat: testcase/testsuite config support getting variables by function feat: har2case with request cookies feat: log request/response headers and body with indent Fixed fix: extract response cookies fix: handle errors when no valid testcases generated Changed change: har2case do not ignore request headers, except for header startswith :","title":"3.0.4 (2020-05-19)"},{"location":"CHANGELOG/#303-2020-05-17","text":"Fixed fix: compatibility with testcase file path includes dots, space and minus sign fix: testcase generator, validate content.xxx => body.xxx fix: scaffold for v3","title":"3.0.3 (2020-05-17)"},{"location":"CHANGELOG/#302-2020-05-16","text":"Added feat: add make sub-command to generate python testcases from YAML/JSON feat: format generated python testcases with black test: add postman echo & httpbin as testcase examples Changed refactor all replace jsonschema validation with pydantic remove compatibility with testcase/testsuite format v1 replace unittest with pytest remove builtin html report, allure will be used with pytest later remove locust support temporarily update command line interface","title":"3.0.2 (2020-05-16)"},{"location":"CHANGELOG/#301-2020-03-24","text":"Changed remove sentry sdk","title":"3.0.1 (2020-03-24)"},{"location":"CHANGELOG/#300-2020-03-10","text":"Added feat: dump log for each testcase feat: add default header HRUN-Request-ID for each testcase #721 Changed remove support for Python 2.7 replace logging with loguru replace string format with f-string remove dependency colorama and colorlog generate reports/logs folder in current working directory remove cli --validate remove cli --pretty","title":"3.0.0 (2020-03-10)"},{"location":"installation/","text":"HttpRunner is developed with Python, it supports Python 3.6+ and most operating systems. Combination of Python 3.6/3.7/3.8 and macOS/Linux/Windows are tested continuously on GitHub-Actions . Installation \u00b6 HttpRunner is available on PyPI and can be installed through pip . $ pip3 install httprunner If you want to keep up with the latest version, you can install with github repository url. $ pip3 install git+https://github.com/httprunner/httprunner.git@master If\b you have installed HttpRunner before and want to upgrade to the latest version, you can use the -U option. $ pip3 install -U httprunner $ pip3 install -U git+https://github.com/httprunner/httprunner.git@master Check Installation \u00b6 When HttpRunner is installed, 4 commands will be added in your system. httprunner : main command, used for all functions hrun : alias for httprunner run , used to run YAML/JSON/pytest testcases hmake : alias for httprunner make , used to convert YAML/JSON testcases to pytest files har2case : alias for httprunner har2case , used to convert HAR to YAML/JSON testcases To see HttpRunner version: $ httprunner -V # hrun -V 3.0.10 To see available options, run: $ httprunner -h usage: httprunner [-h] [-V] {run,startproject,har2case,make} ... One-stop solution for HTTP(S) testing. positional arguments: {run,startproject,har2case,make} sub-command help run Make HttpRunner testcases and run with pytest. startproject Create a new project with template structure. har2case Convert HAR(HTTP Archive) to YAML/JSON testcases for HttpRunner. make Convert YAML/JSON testcases to pytest cases. optional arguments: -h, --help show this help message and exit -V, --version show version","title":"Installation"},{"location":"installation/#installation","text":"HttpRunner is available on PyPI and can be installed through pip . $ pip3 install httprunner If you want to keep up with the latest version, you can install with github repository url. $ pip3 install git+https://github.com/httprunner/httprunner.git@master If\b you have installed HttpRunner before and want to upgrade to the latest version, you can use the -U option. $ pip3 install -U httprunner $ pip3 install -U git+https://github.com/httprunner/httprunner.git@master","title":"Installation"},{"location":"installation/#check-installation","text":"When HttpRunner is installed, 4 commands will be added in your system. httprunner : main command, used for all functions hrun : alias for httprunner run , used to run YAML/JSON/pytest testcases hmake : alias for httprunner make , used to convert YAML/JSON testcases to pytest files har2case : alias for httprunner har2case , used to convert HAR to YAML/JSON testcases To see HttpRunner version: $ httprunner -V # hrun -V 3.0.10 To see available options, run: $ httprunner -h usage: httprunner [-h] [-V] {run,startproject,har2case,make} ... One-stop solution for HTTP(S) testing. positional arguments: {run,startproject,har2case,make} sub-command help run Make HttpRunner testcases and run with pytest. startproject Create a new project with template structure. har2case Convert HAR(HTTP Archive) to YAML/JSON testcases for HttpRunner. make Convert YAML/JSON testcases to pytest cases. optional arguments: -h, --help show this help message and exit -V, --version show version","title":"Check Installation"},{"location":"quickstart/","text":"Quick Start \u00b6 First of all, remember HttpRunner is a simple yet powerful HTTP(S) testing framework. This document will help you to learn HttpRunner in 10 minutes.","title":"Quick Start"},{"location":"quickstart/#quick-start","text":"First of all, remember HttpRunner is a simple yet powerful HTTP(S) testing framework. This document will help you to learn HttpRunner in 10 minutes.","title":"Quick Start"},{"location":"sponsors/","text":"\u8d5e\u52a9\u5546 \u00b6 \u611f\u8c22\u5404\u4f4d\u5bf9 HttpRunner \u7684\u8d5e\u52a9\u652f\u6301\uff01 \u91d1\u724c\u8d5e\u52a9\u5546\uff08Gold Sponsor\uff09 \u00b6 \u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f\u4e1a\u754c\u9886\u5148\u7684\u6d4b\u8bd5\u5f00\u53d1\u6280\u672f\u9ad8\u7aef\u6559\u80b2\u54c1\u724c\uff0c\u96b6\u5c5e\u4e8e\u6d4b\u5427\uff08\u5317\u4eac\uff09\u79d1\u6280\u6709\u9650\u516c\u53f8\u3002\u5b66\u9662\u8bfe\u7a0b\u5747\u7531 BAT \u4e00\u7ebf\u6d4b\u8bd5\u5927\u5496\u6267\u6559\uff0c\u63d0\u4f9b\u5b9e\u6218\u9a71\u52a8\u7684\u63a5\u53e3\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u79fb\u52a8\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u6027\u80fd\u6d4b\u8bd5\u3001\u6301\u7eed\u96c6\u6210\u4e0e DevOps \u7b49\u6280\u672f\u57f9\u8bad\uff0c\u4ee5\u53ca\u6d4b\u8bd5\u5f00\u53d1\u4f18\u79c0\u4eba\u624d\u5185\u63a8\u670d\u52a1\u3002 \u70b9\u51fb\u5b66\u4e60! \u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f HttpRunner \u7684\u9996\u5bb6\u91d1\u724c\u8d5e\u52a9\u5546\u3002 \u5f00\u6e90\u670d\u52a1\u8d5e\u52a9\u5546\uff08Open Source Sponsor\uff09 \u00b6 HttpRunner is in Sentry Sponsored plan. \u6210\u4e3a\u8d5e\u52a9\u5546 \u00b6 \u5982\u679c\u4f60\u6240\u5728\u7684\u516c\u53f8\u6216\u4e2a\u4eba\u4e5f\u60f3\u5bf9 HttpRunner \u8fdb\u884c\u8d5e\u52a9\uff0c\u53ef\u53c2\u8003\u5982\u4e0b\u65b9\u6848\uff0c\u5177\u4f53\u53ef\u8054\u7cfb \u9879\u76ee\u4f5c\u8005 \u3002 \u7b49\u7ea7 \u91d1\u724c\u8d5e\u52a9\u5546 \uff08Gold Sponsor\uff09 \u94f6\u724c\u8d5e\u52a9\u5546 \uff08Silver Sponsor\uff09 \u4e2a\u4eba\u8d5e\u8d4f \u91d1\u989d \uffe510000/\u5e74 \uffe55000/\u5e74 \u4efb\u610f \u6743\u76ca \u516c\u53f8 logo\uff08\u5927\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 150 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u516c\u53f8 logo\uff08\u4e2d\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 50 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u4e2a\u4eba ID \u548c\u94fe\u63a5\u5c55\u793a\u5728 sponsors.md","title":"Sponsors"},{"location":"sponsors/#_1","text":"\u611f\u8c22\u5404\u4f4d\u5bf9 HttpRunner \u7684\u8d5e\u52a9\u652f\u6301\uff01","title":"\u8d5e\u52a9\u5546"},{"location":"sponsors/#gold-sponsor","text":"\u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f\u4e1a\u754c\u9886\u5148\u7684\u6d4b\u8bd5\u5f00\u53d1\u6280\u672f\u9ad8\u7aef\u6559\u80b2\u54c1\u724c\uff0c\u96b6\u5c5e\u4e8e\u6d4b\u5427\uff08\u5317\u4eac\uff09\u79d1\u6280\u6709\u9650\u516c\u53f8\u3002\u5b66\u9662\u8bfe\u7a0b\u5747\u7531 BAT \u4e00\u7ebf\u6d4b\u8bd5\u5927\u5496\u6267\u6559\uff0c\u63d0\u4f9b\u5b9e\u6218\u9a71\u52a8\u7684\u63a5\u53e3\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u79fb\u52a8\u81ea\u52a8\u5316\u6d4b\u8bd5\u3001\u6027\u80fd\u6d4b\u8bd5\u3001\u6301\u7eed\u96c6\u6210\u4e0e DevOps \u7b49\u6280\u672f\u57f9\u8bad\uff0c\u4ee5\u53ca\u6d4b\u8bd5\u5f00\u53d1\u4f18\u79c0\u4eba\u624d\u5185\u63a8\u670d\u52a1\u3002 \u70b9\u51fb\u5b66\u4e60! \u970d\u683c\u6c83\u5179\u6d4b\u8bd5\u5b66\u9662 \u662f HttpRunner \u7684\u9996\u5bb6\u91d1\u724c\u8d5e\u52a9\u5546\u3002","title":"\u91d1\u724c\u8d5e\u52a9\u5546\uff08Gold Sponsor\uff09"},{"location":"sponsors/#open-source-sponsor","text":"HttpRunner is in Sentry Sponsored plan.","title":"\u5f00\u6e90\u670d\u52a1\u8d5e\u52a9\u5546\uff08Open Source Sponsor\uff09"},{"location":"sponsors/#_2","text":"\u5982\u679c\u4f60\u6240\u5728\u7684\u516c\u53f8\u6216\u4e2a\u4eba\u4e5f\u60f3\u5bf9 HttpRunner \u8fdb\u884c\u8d5e\u52a9\uff0c\u53ef\u53c2\u8003\u5982\u4e0b\u65b9\u6848\uff0c\u5177\u4f53\u53ef\u8054\u7cfb \u9879\u76ee\u4f5c\u8005 \u3002 \u7b49\u7ea7 \u91d1\u724c\u8d5e\u52a9\u5546 \uff08Gold Sponsor\uff09 \u94f6\u724c\u8d5e\u52a9\u5546 \uff08Silver Sponsor\uff09 \u4e2a\u4eba\u8d5e\u8d4f \u91d1\u989d \uffe510000/\u5e74 \uffe55000/\u5e74 \u4efb\u610f \u6743\u76ca \u516c\u53f8 logo\uff08\u5927\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 150 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u516c\u53f8 logo\uff08\u4e2d\uff09\u548c\u94fe\u63a5\u5c55\u793a\u5728 README.md 50 \u5b57\u7684\u5ba3\u4f20\u6587\u6848 \u4e2a\u4eba ID \u548c\u94fe\u63a5\u5c55\u793a\u5728 sponsors.md","title":"\u6210\u4e3a\u8d5e\u52a9\u5546"},{"location":"dev/models/","text":"Models \u00b6 HttpRunner v3.x uses pydantic to define models of testcase.","title":"Models"},{"location":"dev/models/#models","text":"HttpRunner v3.x uses pydantic to define models of testcase.","title":"Models"},{"location":"user/gen_tests/","text":"Record & Generate testcase \u00b6 capture HTTP request and response \u00b6 Before we write testcases, we should know the details of the API. It is a good choice to use a web debugging proxy tool like Charles Proxy to capture the HTTP traffic. For example, the image below illustrates post form data to postman-echo.com . export sessions to HAR file \u00b6 Then we can select captured request & response and export sessions to HTTP archive (.har) file. generate testcase with har2case \u00b6 When you get HAR file, you can use builtin command har2case to convert it to HttpRunner testcase. help \u00b6 $ har2case -h usage: har2case har2case [-h] [-2y] [-2j] [--filter FILTER] [--exclude EXCLUDE] [har_source_file] positional arguments: har_source_file Specify HAR source file optional arguments: -h, --help show this help message and exit -2y, --to-yml, --to-yaml Convert to YAML format, if not specified, convert to pytest format by default. -2j, --to-json Convert to JSON format, if not specified, convert to pytest format by default. --filter FILTER Specify filter keyword, only url include filter string will be converted. --exclude EXCLUDE Specify exclude keyword, url that includes exclude string will be ignored, multiple keywords can be joined with '|' generate testcase (pytest) \u00b6 Since HttpRunner 3.0.7 , har2case will convert HAR file to pytest by default, and it is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. $ har2case har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:08:01.191 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.har 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:08:01.194 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted. 2020-06-15 15:08:01.469 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py The generated pytest file is a standard Python file shown as below. # NOTE: Generated By HttpRunner v3.0.12 # FROM: har/postman-echo-post-form.har from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCasePostmanEchoPostForm ( HttpRunner ): config = Config ( \"testcase description\" ) . verify ( False ) teststeps = [ Step ( RunRequest ( \"/get\" ) . get ( \"https://postman-echo.com/get\" ) . with_params ( ** { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ) ), Step ( RunRequest ( \"/post\" ) . post ( \"https://postman-echo.com/post\" ) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . with_data ({ \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.data\" , \"\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/post\" ) ), ] if __name__ == \"__main__\" : TestCasePostmanEchoPostForm () . test_start () And it can be run with hrun command or the native pytest command. In fact, hrun is only a wrapper of pytest , thus the effect is basically the same. $ hrun har/postman_echo_post_form_test.py 2020-06-15 15:23:03.502 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:23:03.503 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... All done! \u2728 \ud83c\udf70 \u2728 1 file left unchanged. 2020-06-15 15:23:03.662 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.60s ======================================================================= $ pytest har/postman_echo_post_form_test.py ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ================================================================= 1 passed, 1 warning in 4.11s ================================================================== generate testcase (YAML/JSON) \u00b6 Of course, you can also generate former YAML/JSON testcase format. Just add -2y/--to-yml or -2j/--to-json argument to har2case . $ har2case har/postman-echo-post-form.har -2j 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:32:02.958 | INFO | httprunner.ext.har2case.utils:dump_json:122 - dump testcase to JSON format. 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.utils:dump_json:131 - Generate JSON testcase successfully: har/postman-echo-post-form.json 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: har/postman-echo-post-form.json { \"config\" : { \"name\" : \"testcase description\" , \"variables\" : {}, \"verify\" : false }, \"teststeps\" : [ { \"name\" : \"/get\" , \"request\" : { \"url\" : \"https://postman-echo.com/get\" , \"params\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }, \"method\" : \"GET\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ] } ] }, { \"name\" : \"/post\" , \"request\" : { \"url\" : \"https://postman-echo.com/post\" , \"method\" : \"POST\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"data\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.data\" , \"\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/post\" ] } ] } ] } The YAML/JSON testcase has the same info with pytest testcase, and you can run YAML/JSON testcase with hrun command. $ hrun har/postman-echo-post-form.json 2020-06-15 15:37:15.621 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:37:15.623 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.json 2020-06-15 15:37:15.625 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:37:15.625 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-15 15:37:15.962 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.03s =======================================================================","title":"Record & Generate testcase"},{"location":"user/gen_tests/#record-generate-testcase","text":"","title":"Record & Generate testcase"},{"location":"user/gen_tests/#capture-http-request-and-response","text":"Before we write testcases, we should know the details of the API. It is a good choice to use a web debugging proxy tool like Charles Proxy to capture the HTTP traffic. For example, the image below illustrates post form data to postman-echo.com .","title":"capture HTTP request and response"},{"location":"user/gen_tests/#export-sessions-to-har-file","text":"Then we can select captured request & response and export sessions to HTTP archive (.har) file.","title":"export sessions to HAR file"},{"location":"user/gen_tests/#generate-testcase-with-har2case","text":"When you get HAR file, you can use builtin command har2case to convert it to HttpRunner testcase.","title":"generate testcase with har2case"},{"location":"user/gen_tests/#help","text":"$ har2case -h usage: har2case har2case [-h] [-2y] [-2j] [--filter FILTER] [--exclude EXCLUDE] [har_source_file] positional arguments: har_source_file Specify HAR source file optional arguments: -h, --help show this help message and exit -2y, --to-yml, --to-yaml Convert to YAML format, if not specified, convert to pytest format by default. -2j, --to-json Convert to JSON format, if not specified, convert to pytest format by default. --filter FILTER Specify filter keyword, only url include filter string will be converted. --exclude EXCLUDE Specify exclude keyword, url that includes exclude string will be ignored, multiple keywords can be joined with '|'","title":"help"},{"location":"user/gen_tests/#generate-testcase-pytest","text":"Since HttpRunner 3.0.7 , har2case will convert HAR file to pytest by default, and it is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. $ har2case har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:08:01.187 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:08:01.191 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:08:01.191 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.har 2020-06-15 15:08:01.193 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:08:01.194 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted. 2020-06-15 15:08:01.469 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py The generated pytest file is a standard Python file shown as below. # NOTE: Generated By HttpRunner v3.0.12 # FROM: har/postman-echo-post-form.har from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCasePostmanEchoPostForm ( HttpRunner ): config = Config ( \"testcase description\" ) . verify ( False ) teststeps = [ Step ( RunRequest ( \"/get\" ) . get ( \"https://postman-echo.com/get\" ) . with_params ( ** { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ) ), Step ( RunRequest ( \"/post\" ) . post ( \"https://postman-echo.com/post\" ) . with_headers ( ** { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" , } ) . with_cookies ( ** { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2 %2F rD9cxUhQemIsm78nifYZYHpPCU\" } ) . with_data ({ \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( 'headers.\"Content-Type\"' , \"application/json; charset=utf-8\" ) . assert_equal ( \"body.data\" , \"\" ) . assert_equal ( \"body.url\" , \"https://postman-echo.com/post\" ) ), ] if __name__ == \"__main__\" : TestCasePostmanEchoPostForm () . test_start () And it can be run with hrun command or the native pytest command. In fact, hrun is only a wrapper of pytest , thus the effect is basically the same. $ hrun har/postman_echo_post_form_test.py 2020-06-15 15:23:03.502 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:23:03.502 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:23:03.503 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... All done! \u2728 \ud83c\udf70 \u2728 1 file left unchanged. 2020-06-15 15:23:03.662 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.60s ======================================================================= $ pytest har/postman_echo_post_form_test.py ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ================================================================= 1 passed, 1 warning in 4.11s ==================================================================","title":"generate testcase (pytest)"},{"location":"user/gen_tests/#generate-testcase-yamljson","text":"Of course, you can also generate former YAML/JSON testcase format. Just add -2y/--to-yml or -2j/--to-json argument to har2case . $ har2case har/postman-echo-post-form.har -2j 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:gen_testcase:332 - Start to generate testcase from har/postman-echo-post-form.har 2020-06-15 15:32:02.955 | INFO | httprunner.ext.har2case.core:_make_testcase:323 - Extract info from HAR file and prepare for testcase. 2020-06-15 15:32:02.958 | INFO | httprunner.ext.har2case.utils:dump_json:122 - dump testcase to JSON format. 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.utils:dump_json:131 - Generate JSON testcase successfully: har/postman-echo-post-form.json 2020-06-15 15:32:02.959 | INFO | httprunner.ext.har2case.core:gen_testcase:353 - generated testcase: har/postman-echo-post-form.json { \"config\" : { \"name\" : \"testcase description\" , \"variables\" : {}, \"verify\" : false }, \"teststeps\" : [ { \"name\" : \"/get\" , \"request\" : { \"url\" : \"https://postman-echo.com/get\" , \"params\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" }, \"method\" : \"GET\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"6606343b-10e5-4165-a89f-6c301b762ce0\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/get?foo1=bar1&foo2=bar2\" ] } ] }, { \"name\" : \"/post\" , \"request\" : { \"url\" : \"https://postman-echo.com/post\" , \"method\" : \"POST\" , \"cookies\" : { \"sails.sid\" : \"s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"headers\" : { \"User-Agent\" : \"PostmanRuntime/7.24.1\" , \"Accept\" : \"*/*\" , \"Cache-Control\" : \"no-cache\" , \"Postman-Token\" : \"3e408e9d-25ca-4b31-b04b-7f4898a8cd49\" , \"Host\" : \"postman-echo.com\" , \"Accept-Encoding\" : \"gzip, deflate, br\" , \"Connection\" : \"keep-alive\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , \"Content-Length\" : \"19\" , \"Cookie\" : \"sails.sid=s%3AQG_EVeNRw8k1xxZ6v_SG401VTpmJDSRu.fTAGx3JnZUT7S0c2%2FrD9cxUhQemIsm78nifYZYHpPCU\" }, \"data\" : { \"foo1\" : \"bar1\" , \"foo2\" : \"bar2\" } }, \"validate\" : [ { \"eq\" : [ \"status_code\" , 200 ] }, { \"eq\" : [ \"headers.Content-Type\" , \"application/json; charset=utf-8\" ] }, { \"eq\" : [ \"body.data\" , \"\" ] }, { \"eq\" : [ \"body.url\" , \"https://postman-echo.com/post\" ] } ] } ] } The YAML/JSON testcase has the same info with pytest testcase, and you can run YAML/JSON testcase with hrun command. $ hrun har/postman-echo-post-form.json 2020-06-15 15:37:15.621 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/Desktop/demo/.env 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 15:37:15.622 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 15:37:15.623 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/Desktop/demo/har/postman-echo-post-form.json 2020-06-15 15:37:15.625 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py 2020-06-15 15:37:15.625 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/Desktop/demo/har/postman_echo_post_form_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-15 15:37:15.962 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/Desktop/demo plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item har/postman_echo_post_form_test.py . [100%] ======================================================================= 1 passed in 2.03s =======================================================================","title":"generate testcase (YAML/JSON)"},{"location":"user/run_testcase/","text":"Run Testcase \u00b6 Once testcase is ready, you can run testcase with hrun command. Notice, hrun is an command alias of httprunner run , they have the same effect. hrun = httprunner run run testcases in diverse ways \u00b6 HttpRunner can run testcases in diverse ways. You can run single testcase by specifying testcase file path. $ hrun path/to/testcase1 You can also run several testcases by specifying multiple testcase file paths. $ hrun path/to/testcase1 path/to/testcase2 If you want to run testcases of a whole project, you can achieve this goal by specifying the project folder path. $ hrun path/to/testcase_folder/ run YAML/JSON testcases \u00b6 If your testcases are written in YAML/JSON format, hrun will firstly convert YAML/JSON testcases to pytest(python) files, and run with pytest command. That is to say, hrun = make + pytest In most cases, the generated pytest files are in the same folder next to origin YAML/JSON files, with the same file name except adding _test suffix and replace extension .yml/yaml/.json with .py . /path/to/example.yml => /path/to/example_test.py However, if the testcase folder name or file name contains symbols like dot, hyphen or space, these symbols will be replaced with underscore in order to avoid syntax error in python class importing (testcase reference). Also, folder/file name starts with digit will be adding a prefix T because python module and class name can not be started with digit. path 1/a.b-2/3.yml => path_1/a_b_2/T3_test.py run pytest testcases \u00b6 If your testcases are written in pytest format, or you want to run pytest files converted from YAML/JSON testcases, hrun and pytest commands are both okay. What you need to remember is that hrun only wraps pytest , thus all the arguments of pytest can be used with hrun . $ 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 --import-mode={prepend,append} prepend/append to sys.path when importing test modules, default is to prepend. --pdb start the interactive Python debugger on errors or KeyboardInterrupt. --pdbcls=modulename:classname start a custom interactive Python debugger on errors. For example: --pdbcls=IPython.terminal.debugger:TerminalPdb --trace Immediately break when running each test. --capture=method per-test capturing method: one of fd|sys|no|tee-sys. -s shortcut for --capture=no. --runxfail report the results of xfail tests as if they were not marked --lf, --last-failed rerun only the tests that failed at the last run (or all if none failed) --ff, --failed-first run all tests but run the last failures first. This may re-order tests and thus lead to repeated fixture setup/teardown --nf, --new-first run tests from new files first, then the rest of the tests sorted by file mtime --cache-show=[CACHESHOW] show cache contents, don't perform collection or tests. Optional argument: glob (default: '*'). --cache-clear remove all cache contents at start of test run. --lfnf={all,none}, --last-failed-no-failures={all,none} which tests to run with no previously (known) failures. --sw, --stepwise exit on test failure and continue from last failing test next time --stepwise-skip ignore the first failing test but stop on the next failing test --allure-severities=SEVERITIES_SET Comma-separated list of severity names. Tests only with these severities will be run. Possible values are: blocker, critical, normal, minor, trivial. --allure-epics=EPICS_SET Comma-separated list of epic names. Run tests that have at least one of the specified feature labels. --allure-features=FEATURES_SET Comma-separated list of feature names. Run tests that have at least one of the specified feature labels. --allure-stories=STORIES_SET Comma-separated list of story names. Run tests that have at least one of the specified story labels. --allure-link-pattern=LINK_TYPE:LINK_PATTERN Url pattern for link type. Allows short links in test, like 'issue-1'. Text will be formatted to full url with python str.format(). reporting: --durations=N show N slowest setup/test durations (N=0 for all). -v, --verbose increase verbosity. -q, --quiet decrease verbosity. --verbosity=VERBOSE set verbosity. Default is 0. -r chars show extra test summary info as specified by chars: (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed (p/P), or (A)ll. (w)arnings are enabled by default (see --disable-warnings), 'N' can be used to reset the list. (default: 'fE'). --disable-warnings, --disable-pytest-warnings disable warnings summary -l, --showlocals show locals in tracebacks (disabled by default). --tb=style traceback print mode (auto/long/short/line/native/no). --show-capture={no,stdout,stderr,log,all} Controls how captured stdout/stderr/log is shown on failed tests. Default is 'all'. --full-trace don't cut any tracebacks (default is to cut). --color=color color terminal output (yes/no/auto). --pastebin=mode send failed|all info to bpaste.net pastebin service. --junit-xml=path create junit-xml style report file at given path. --junit-prefix=str prepend prefix to classnames in junit-xml output --result-log=path DEPRECATED path for machine-readable result log. --html=path create html report file at given path. --self-contained-html create a self-contained html file containing all necessary styles, scripts, and images - this means that the report may not render or function where CSP restrictions are in place (see https://developer.mozilla.org/docs/Web/Security/CSP) --css=path append given css file content to report style file. collection: --collect-only, --co only collect tests, don't execute them. --pyargs try to interpret all arguments as python packages. --ignore=path ignore path during collection (multi-allowed). --ignore-glob=path ignore path pattern during collection (multi-allowed). --deselect=nodeid_prefix deselect item (via node id prefix) during collection (multi-allowed). --confcutdir=dir only load conftest.py's relative to specified dir. --noconftest Don't load any conftest.py files. --keep-duplicates Keep duplicate tests. --collect-in-virtualenv Don't ignore tests in a local virtualenv directory --doctest-modules run doctests in all .py modules --doctest-report={none,cdiff,ndiff,udiff,only_first_failure} choose another output format for diffs on doctest failure --doctest-glob=pat doctests file matching pattern, default: test*.txt --doctest-ignore-import-errors ignore doctest ImportErrors --doctest-continue-on-failure for a given doctest, continue to run after the first failure test session debugging and configuration: --basetemp=dir base temporary directory for this test run.(warning: this directory is removed if it exists) -V, --version display pytest version and information about plugins. -h, --help show help message and configuration info -p name early-load given plugin module name or entry point (multi-allowed). To avoid loading of plugins, use the `no:` prefix, e.g. `no:doctest`. --trace-config trace considerations of conftest.py files. --debug store internal tracing debug information in 'pytestdebug.log'. -o OVERRIDE_INI, --override-ini=OVERRIDE_INI override ini option with \"option=value\" style, e.g. `-o xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools. 'plain' performs no assertion debugging. 'rewrite' (the default) rewrites assert statements in test modules on import to provide assert expression information. --setup-only only setup fixtures, do not execute tests. --setup-show show setup of fixtures while executing tests. --setup-plan show what fixtures and tests would be executed but don't execute anything. pytest-warnings: -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS set which warnings to report, see -W option of python itself. logging: --no-print-logs disable printing caught logs on failed tests. --log-level=LEVEL level of messages to catch/display. Not set by default, so it depends on the root/parent log handler's effective level, where it is \"WARNING\" by default. --log-format=LOG_FORMAT log format as used by the logging module. --log-date-format=LOG_DATE_FORMAT log date format as used by the logging module. --log-cli-level=LOG_CLI_LEVEL cli logging level. --log-cli-format=LOG_CLI_FORMAT log format as used by the logging module. --log-cli-date-format=LOG_CLI_DATE_FORMAT log date format as used by the logging module. --log-file=LOG_FILE path to a file when logging will be written to. --log-file-level=LOG_FILE_LEVEL log file logging level. --log-file-format=LOG_FILE_FORMAT log format as used by the logging module. --log-file-date-format=LOG_FILE_DATE_FORMAT log date format as used by the logging module. --log-auto-indent=LOG_AUTO_INDENT Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer. reporting: --alluredir=DIR Generate Allure report in the specified directory (may not exist) --clean-alluredir Clean alluredir folder if it exists --allure-no-capture Do not attach pytest captured logging/stdout/stderr to report custom options: --metadata=key value additional metadata. --metadata-from-json=METADATA_FROM_JSON additional metadata from a json string. [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found: markers (linelist): markers for test functions empty_parameter_set_mark (string): default marker for empty parametersets norecursedirs (args): directory patterns to avoid for recursion testpaths (args): directories to search for tests when no files or directories are given in the command line. usefixtures (args): list of default fixtures to be used with this project python_files (args): glob-style file patterns for Python test module discovery python_classes (args): prefixes or glob names for Python test class discovery python_functions (args): prefixes or glob names for Python test function and method discovery disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool): disable string escape non-ascii characters, might cause unwanted side effects(use at your own risk) console_output_style (string): console output: \"classic\", or with additional progress information (\"progress\" (percentage) | \"count\"). xfail_strict (bool): default for the strict parameter of xfail markers when not given explicitly (default: False) enable_assertion_pass_hook (bool): Enables the pytest_assertion_pass hook.Make sure to delete any previously generated pyc cache files. junit_suite_name (string): Test suite name for JUnit report junit_logging (string): Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|all junit_log_passing_tests (bool): Capture log information for passing tests to JUnit report: junit_duration_report (string): Duration time to report: one of total|call junit_family (string): Emit XML for schema: one of legacy|xunit1|xunit2 doctest_optionflags (args): option flags for doctests doctest_encoding (string): encoding used for doctest files cache_dir (string): cache directory path. filterwarnings (linelist): Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings. log_print (bool): default value for --no-print-logs log_level (string): default value for --log-level log_format (string): default value for --log-format log_date_format (string): default value for --log-date-format log_cli (bool): enable log display during test run (also known as \"live logging\"). log_cli_level (string): default value for --log-cli-level log_cli_format (string): default value for --log-cli-format log_cli_date_format (string): default value for --log-cli-date-format log_file (string): default value for --log-file log_file_level (string): default value for --log-file-level log_file_format (string): default value for --log-file-format log_file_date_format (string): default value for --log-file-date-format log_auto_indent (string): default value for --log-auto-indent faulthandler_timeout (string): Dump the traceback of all threads if a test takes more than TIMEOUT seconds to finish. Not available on Windows. addopts (args): extra command line options minversion (string): minimally required pytest version render_collapsed (bool): Open the report with all rows collapsed. Useful for very large reports environment variables: PYTEST_ADDOPTS extra command line options PYTEST_PLUGINS comma-separated plugins to load during startup PYTEST_DISABLE_PLUGIN_AUTOLOAD set to disable plugin auto-loading PYTEST_DEBUG set to enable debug tracing of pytest's internals to see available markers type: pytest --markers to see available fixtures type: pytest --fixtures (shown according to specified file_or_dir or current dir if not specified; fixtures with leading '_' are only shown with the '-v' option execution logs \u00b6 By default, hrun will not print details of request and response data. $ hrun examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:39:41.041 | INFO | httprunner.make:make_testcase:317 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:39:41.042 | INFO | httprunner.make:make_testcase:390 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:39:41.042 | INFO | httprunner.make:format_pytest_with_black:154 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-17 15:39:41.315 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.13 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item examples/postman_echo/request_methods/request_with_functions_test.py . [100%] ======================================================================= 1 passed in 2.98s ======================================================================= If you want to view details of request & response data, extraction and validation, you can add an argument -s (shortcut for --capture=no ). $ hrun -s examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:42:54.369 | INFO | httprunner.make:make_testcase:317 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:42:54.369 | INFO | httprunner.make:make_testcase:390 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:42:54.370 | INFO | httprunner.make:format_pytest_with_black:154 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-17 15:42:54.699 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.13 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:42:55.017 | INFO | httprunner.runner:test_start:435 - Start to run testcase: request methods testcase with functions, TestCase ID: cc404c49-000f-485c-b4c1-ac3367a053fe 2020-06-17 15:42:55.018 | INFO | httprunner.runner:__run_step:278 - run step begin: get with params >>>>>> 2020-06-17 15:42:56.326 | DEBUG | httprunner.client:log_print:40 - ================== request details ================== method : GET url : https://postman-echo.com/get?foo1=bar11&foo2=bar21&sum_v=3 headers : { \"User-Agent\": \"HttpRunner/3.0.13\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"Connection\": \"keep-alive\", \"HRUN-Request-ID\": \"HRUN-cc404c49-000f-485c-b4c1-ac3367a053fe-775018\", \"Content-Length\": \"2\", \"Content-Type\": \"application/json\" } cookies : {} body : {} 2020-06-17 15:42:56.327 | DEBUG | httprunner.client:log_print:40 - ================== response details ================== status_code : 200 headers : { \"Date\": \"Wed, 17 Jun 2020 07:42:56 GMT\", \"Content-Type\": \"application/json; charset=utf-8\", \"Content-Length\": \"477\", \"Connection\": \"keep-alive\", \"ETag\": \"W/\\\"1dd-2JtBYPcnh8D6fqLz8KFn16Oq1R0\\\"\", \"Vary\": \"Accept-Encoding\", \"set-cookie\": \"sails.sid=s%3A6J_EtUk3nkL_C2xtx-NtAXrlA5wPxEgk.gIO2yBbtvGWIIgQ%2F2mZhMkU669G3F60cvLAPWbwyoGM; Path=/; HttpOnly\" } cookies : { \"sails.sid\": \"s%3A6J_EtUk3nkL_C2xtx-NtAXrlA5wPxEgk.gIO2yBbtvGWIIgQ%2F2mZhMkU669G3F60cvLAPWbwyoGM\" } encoding : utf-8 content_type : application/json; charset=utf-8 body : { \"args\": { \"foo1\": \"bar11\", \"foo2\": \"bar21\", \"sum_v\": \"3\" }, \"headers\": { \"x-forwarded-proto\": \"https\", \"x-forwarded-port\": \"443\", \"host\": \"postman-echo.com\", \"x-amzn-trace-id\": \"Root=1-5ee9c980-d8e98cc72a26ef24f5819ce3\", \"content-length\": \"2\", \"user-agent\": \"HttpRunner/3.0.13\", \"accept-encoding\": \"gzip, deflate\", \"accept\": \"*/*\", \"hrun-request-id\": \"HRUN-cc404c49-000f-485c-b4c1-ac3367a053fe-775018\", \"content-type\": \"application/json\" }, \"url\": \"https://postman-echo.com/get?foo1=bar11&foo2=bar21&sum_v=3\" } 2020-06-17 15:42:56.328 | INFO | httprunner.client:request:203 - status_code: 200, response_time(ms): 1307.33 ms, response_length: 477 bytes 2020-06-17 15:42:56.328 | INFO | httprunner.response:extract:152 - extract mapping: {'foo3': 'bar21'} 2020-06-17 15:42:56.328 | INFO | httprunner.response:validate:209 - assert status_code equal 200(int) ==> pass 2020-06-17 15:42:56.329 | INFO | httprunner.response:validate:209 - assert body.args.foo1 equal bar11(str) ==> pass 2020-06-17 15:42:56.329 | INFO | httprunner.response:validate:209 - assert body.args.sum_v equal 3(str) ==> pass 2020-06-17 15:42:56.329 | INFO | httprunner.response:validate:209 - assert body.args.foo2 equal bar21(str) ==> pass 2020-06-17 15:42:56.330 | INFO | httprunner.runner:__run_step:290 - run step end: get with params <<<<<< 2020-06-17 15:42:57.019 | INFO | httprunner.runner:test_start:444 - generate testcase log: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/logs/cc404c49-000f-485c-b4c1-ac3367a053fe.run.log . ======================================================================= 1 passed in 2.13s ======================================================================= Also, an execution log file will be generated for each testcase, located in /logs/TestCaseID.run.log . TestCase ID & Request ID \u00b6 For the sake of troubleshooting, each testcase will generate a unique ID (uuid4), and each request headers will be added a HRUN-Request-ID field with testcase ID automatically. HRUN-Request-ID = \"HRUN--\" timestamp_six_digits = str(int(time.time() * 1000))[-6:]) In other words, all requests in one testcase will have the same HRUN-Request-ID prefix, and each request will have a unique HRUN-Request-ID suffix. arguments for v2.x compatibility \u00b6 Besides all the arguments of pytest , hrun also has several other arguments to keep compatibility with HttpRunner v2.x. --failfast : has no effect, this argument will be removed automatically --report-file : specify html report file path, this argument will be replaced with --html --self-contained-html and generate html report with pytest-html plugin --save-tests : if set, HttpRunner v3.x will create a pytest conftest.py file containing session fixture to aggregate each testcase's summary and dumps to summary.json","title":"Run Testcase"},{"location":"user/run_testcase/#run-testcase","text":"Once testcase is ready, you can run testcase with hrun command. Notice, hrun is an command alias of httprunner run , they have the same effect. hrun = httprunner run","title":"Run Testcase"},{"location":"user/run_testcase/#run-testcases-in-diverse-ways","text":"HttpRunner can run testcases in diverse ways. You can run single testcase by specifying testcase file path. $ hrun path/to/testcase1 You can also run several testcases by specifying multiple testcase file paths. $ hrun path/to/testcase1 path/to/testcase2 If you want to run testcases of a whole project, you can achieve this goal by specifying the project folder path. $ hrun path/to/testcase_folder/","title":"run testcases in diverse ways"},{"location":"user/run_testcase/#run-yamljson-testcases","text":"If your testcases are written in YAML/JSON format, hrun will firstly convert YAML/JSON testcases to pytest(python) files, and run with pytest command. That is to say, hrun = make + pytest In most cases, the generated pytest files are in the same folder next to origin YAML/JSON files, with the same file name except adding _test suffix and replace extension .yml/yaml/.json with .py . /path/to/example.yml => /path/to/example_test.py However, if the testcase folder name or file name contains symbols like dot, hyphen or space, these symbols will be replaced with underscore in order to avoid syntax error in python class importing (testcase reference). Also, folder/file name starts with digit will be adding a prefix T because python module and class name can not be started with digit. path 1/a.b-2/3.yml => path_1/a_b_2/T3_test.py","title":"run YAML/JSON testcases"},{"location":"user/run_testcase/#run-pytest-testcases","text":"If your testcases are written in pytest format, or you want to run pytest files converted from YAML/JSON testcases, hrun and pytest commands are both okay. What you need to remember is that hrun only wraps pytest , thus all the arguments of pytest can be used with hrun . $ 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 --import-mode={prepend,append} prepend/append to sys.path when importing test modules, default is to prepend. --pdb start the interactive Python debugger on errors or KeyboardInterrupt. --pdbcls=modulename:classname start a custom interactive Python debugger on errors. For example: --pdbcls=IPython.terminal.debugger:TerminalPdb --trace Immediately break when running each test. --capture=method per-test capturing method: one of fd|sys|no|tee-sys. -s shortcut for --capture=no. --runxfail report the results of xfail tests as if they were not marked --lf, --last-failed rerun only the tests that failed at the last run (or all if none failed) --ff, --failed-first run all tests but run the last failures first. This may re-order tests and thus lead to repeated fixture setup/teardown --nf, --new-first run tests from new files first, then the rest of the tests sorted by file mtime --cache-show=[CACHESHOW] show cache contents, don't perform collection or tests. Optional argument: glob (default: '*'). --cache-clear remove all cache contents at start of test run. --lfnf={all,none}, --last-failed-no-failures={all,none} which tests to run with no previously (known) failures. --sw, --stepwise exit on test failure and continue from last failing test next time --stepwise-skip ignore the first failing test but stop on the next failing test --allure-severities=SEVERITIES_SET Comma-separated list of severity names. Tests only with these severities will be run. Possible values are: blocker, critical, normal, minor, trivial. --allure-epics=EPICS_SET Comma-separated list of epic names. Run tests that have at least one of the specified feature labels. --allure-features=FEATURES_SET Comma-separated list of feature names. Run tests that have at least one of the specified feature labels. --allure-stories=STORIES_SET Comma-separated list of story names. Run tests that have at least one of the specified story labels. --allure-link-pattern=LINK_TYPE:LINK_PATTERN Url pattern for link type. Allows short links in test, like 'issue-1'. Text will be formatted to full url with python str.format(). reporting: --durations=N show N slowest setup/test durations (N=0 for all). -v, --verbose increase verbosity. -q, --quiet decrease verbosity. --verbosity=VERBOSE set verbosity. Default is 0. -r chars show extra test summary info as specified by chars: (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed (p/P), or (A)ll. (w)arnings are enabled by default (see --disable-warnings), 'N' can be used to reset the list. (default: 'fE'). --disable-warnings, --disable-pytest-warnings disable warnings summary -l, --showlocals show locals in tracebacks (disabled by default). --tb=style traceback print mode (auto/long/short/line/native/no). --show-capture={no,stdout,stderr,log,all} Controls how captured stdout/stderr/log is shown on failed tests. Default is 'all'. --full-trace don't cut any tracebacks (default is to cut). --color=color color terminal output (yes/no/auto). --pastebin=mode send failed|all info to bpaste.net pastebin service. --junit-xml=path create junit-xml style report file at given path. --junit-prefix=str prepend prefix to classnames in junit-xml output --result-log=path DEPRECATED path for machine-readable result log. --html=path create html report file at given path. --self-contained-html create a self-contained html file containing all necessary styles, scripts, and images - this means that the report may not render or function where CSP restrictions are in place (see https://developer.mozilla.org/docs/Web/Security/CSP) --css=path append given css file content to report style file. collection: --collect-only, --co only collect tests, don't execute them. --pyargs try to interpret all arguments as python packages. --ignore=path ignore path during collection (multi-allowed). --ignore-glob=path ignore path pattern during collection (multi-allowed). --deselect=nodeid_prefix deselect item (via node id prefix) during collection (multi-allowed). --confcutdir=dir only load conftest.py's relative to specified dir. --noconftest Don't load any conftest.py files. --keep-duplicates Keep duplicate tests. --collect-in-virtualenv Don't ignore tests in a local virtualenv directory --doctest-modules run doctests in all .py modules --doctest-report={none,cdiff,ndiff,udiff,only_first_failure} choose another output format for diffs on doctest failure --doctest-glob=pat doctests file matching pattern, default: test*.txt --doctest-ignore-import-errors ignore doctest ImportErrors --doctest-continue-on-failure for a given doctest, continue to run after the first failure test session debugging and configuration: --basetemp=dir base temporary directory for this test run.(warning: this directory is removed if it exists) -V, --version display pytest version and information about plugins. -h, --help show help message and configuration info -p name early-load given plugin module name or entry point (multi-allowed). To avoid loading of plugins, use the `no:` prefix, e.g. `no:doctest`. --trace-config trace considerations of conftest.py files. --debug store internal tracing debug information in 'pytestdebug.log'. -o OVERRIDE_INI, --override-ini=OVERRIDE_INI override ini option with \"option=value\" style, e.g. `-o xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools. 'plain' performs no assertion debugging. 'rewrite' (the default) rewrites assert statements in test modules on import to provide assert expression information. --setup-only only setup fixtures, do not execute tests. --setup-show show setup of fixtures while executing tests. --setup-plan show what fixtures and tests would be executed but don't execute anything. pytest-warnings: -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS set which warnings to report, see -W option of python itself. logging: --no-print-logs disable printing caught logs on failed tests. --log-level=LEVEL level of messages to catch/display. Not set by default, so it depends on the root/parent log handler's effective level, where it is \"WARNING\" by default. --log-format=LOG_FORMAT log format as used by the logging module. --log-date-format=LOG_DATE_FORMAT log date format as used by the logging module. --log-cli-level=LOG_CLI_LEVEL cli logging level. --log-cli-format=LOG_CLI_FORMAT log format as used by the logging module. --log-cli-date-format=LOG_CLI_DATE_FORMAT log date format as used by the logging module. --log-file=LOG_FILE path to a file when logging will be written to. --log-file-level=LOG_FILE_LEVEL log file logging level. --log-file-format=LOG_FILE_FORMAT log format as used by the logging module. --log-file-date-format=LOG_FILE_DATE_FORMAT log date format as used by the logging module. --log-auto-indent=LOG_AUTO_INDENT Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer. reporting: --alluredir=DIR Generate Allure report in the specified directory (may not exist) --clean-alluredir Clean alluredir folder if it exists --allure-no-capture Do not attach pytest captured logging/stdout/stderr to report custom options: --metadata=key value additional metadata. --metadata-from-json=METADATA_FROM_JSON additional metadata from a json string. [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found: markers (linelist): markers for test functions empty_parameter_set_mark (string): default marker for empty parametersets norecursedirs (args): directory patterns to avoid for recursion testpaths (args): directories to search for tests when no files or directories are given in the command line. usefixtures (args): list of default fixtures to be used with this project python_files (args): glob-style file patterns for Python test module discovery python_classes (args): prefixes or glob names for Python test class discovery python_functions (args): prefixes or glob names for Python test function and method discovery disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool): disable string escape non-ascii characters, might cause unwanted side effects(use at your own risk) console_output_style (string): console output: \"classic\", or with additional progress information (\"progress\" (percentage) | \"count\"). xfail_strict (bool): default for the strict parameter of xfail markers when not given explicitly (default: False) enable_assertion_pass_hook (bool): Enables the pytest_assertion_pass hook.Make sure to delete any previously generated pyc cache files. junit_suite_name (string): Test suite name for JUnit report junit_logging (string): Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|all junit_log_passing_tests (bool): Capture log information for passing tests to JUnit report: junit_duration_report (string): Duration time to report: one of total|call junit_family (string): Emit XML for schema: one of legacy|xunit1|xunit2 doctest_optionflags (args): option flags for doctests doctest_encoding (string): encoding used for doctest files cache_dir (string): cache directory path. filterwarnings (linelist): Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings. log_print (bool): default value for --no-print-logs log_level (string): default value for --log-level log_format (string): default value for --log-format log_date_format (string): default value for --log-date-format log_cli (bool): enable log display during test run (also known as \"live logging\"). log_cli_level (string): default value for --log-cli-level log_cli_format (string): default value for --log-cli-format log_cli_date_format (string): default value for --log-cli-date-format log_file (string): default value for --log-file log_file_level (string): default value for --log-file-level log_file_format (string): default value for --log-file-format log_file_date_format (string): default value for --log-file-date-format log_auto_indent (string): default value for --log-auto-indent faulthandler_timeout (string): Dump the traceback of all threads if a test takes more than TIMEOUT seconds to finish. Not available on Windows. addopts (args): extra command line options minversion (string): minimally required pytest version render_collapsed (bool): Open the report with all rows collapsed. Useful for very large reports environment variables: PYTEST_ADDOPTS extra command line options PYTEST_PLUGINS comma-separated plugins to load during startup PYTEST_DISABLE_PLUGIN_AUTOLOAD set to disable plugin auto-loading PYTEST_DEBUG set to enable debug tracing of pytest's internals to see available markers type: pytest --markers to see available fixtures type: pytest --fixtures (shown according to specified file_or_dir or current dir if not specified; fixtures with leading '_' are only shown with the '-v' option","title":"run pytest testcases"},{"location":"user/run_testcase/#execution-logs","text":"By default, hrun will not print details of request and response data. $ hrun examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:39:41.041 | INFO | httprunner.make:make_testcase:317 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:39:41.042 | INFO | httprunner.make:make_testcase:390 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:39:41.042 | INFO | httprunner.make:format_pytest_with_black:154 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-17 15:39:41.315 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.13 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item examples/postman_echo/request_methods/request_with_functions_test.py . [100%] ======================================================================= 1 passed in 2.98s ======================================================================= If you want to view details of request & response data, extraction and validation, you can add an argument -s (shortcut for --capture=no ). $ hrun -s examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:42:54.369 | INFO | httprunner.make:make_testcase:317 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions.yml 2020-06-17 15:42:54.369 | INFO | httprunner.make:make_testcase:390 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:42:54.370 | INFO | httprunner.make:format_pytest_with_black:154 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py All done! \u2728 \ud83c\udf70 \u2728 1 file reformatted, 1 file left unchanged. 2020-06-17 15:42:54.699 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.13 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 1 item examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:42:55.017 | INFO | httprunner.runner:test_start:435 - Start to run testcase: request methods testcase with functions, TestCase ID: cc404c49-000f-485c-b4c1-ac3367a053fe 2020-06-17 15:42:55.018 | INFO | httprunner.runner:__run_step:278 - run step begin: get with params >>>>>> 2020-06-17 15:42:56.326 | DEBUG | httprunner.client:log_print:40 - ================== request details ================== method : GET url : https://postman-echo.com/get?foo1=bar11&foo2=bar21&sum_v=3 headers : { \"User-Agent\": \"HttpRunner/3.0.13\", \"Accept-Encoding\": \"gzip, deflate\", \"Accept\": \"*/*\", \"Connection\": \"keep-alive\", \"HRUN-Request-ID\": \"HRUN-cc404c49-000f-485c-b4c1-ac3367a053fe-775018\", \"Content-Length\": \"2\", \"Content-Type\": \"application/json\" } cookies : {} body : {} 2020-06-17 15:42:56.327 | DEBUG | httprunner.client:log_print:40 - ================== response details ================== status_code : 200 headers : { \"Date\": \"Wed, 17 Jun 2020 07:42:56 GMT\", \"Content-Type\": \"application/json; charset=utf-8\", \"Content-Length\": \"477\", \"Connection\": \"keep-alive\", \"ETag\": \"W/\\\"1dd-2JtBYPcnh8D6fqLz8KFn16Oq1R0\\\"\", \"Vary\": \"Accept-Encoding\", \"set-cookie\": \"sails.sid=s%3A6J_EtUk3nkL_C2xtx-NtAXrlA5wPxEgk.gIO2yBbtvGWIIgQ%2F2mZhMkU669G3F60cvLAPWbwyoGM; Path=/; HttpOnly\" } cookies : { \"sails.sid\": \"s%3A6J_EtUk3nkL_C2xtx-NtAXrlA5wPxEgk.gIO2yBbtvGWIIgQ%2F2mZhMkU669G3F60cvLAPWbwyoGM\" } encoding : utf-8 content_type : application/json; charset=utf-8 body : { \"args\": { \"foo1\": \"bar11\", \"foo2\": \"bar21\", \"sum_v\": \"3\" }, \"headers\": { \"x-forwarded-proto\": \"https\", \"x-forwarded-port\": \"443\", \"host\": \"postman-echo.com\", \"x-amzn-trace-id\": \"Root=1-5ee9c980-d8e98cc72a26ef24f5819ce3\", \"content-length\": \"2\", \"user-agent\": \"HttpRunner/3.0.13\", \"accept-encoding\": \"gzip, deflate\", \"accept\": \"*/*\", \"hrun-request-id\": \"HRUN-cc404c49-000f-485c-b4c1-ac3367a053fe-775018\", \"content-type\": \"application/json\" }, \"url\": \"https://postman-echo.com/get?foo1=bar11&foo2=bar21&sum_v=3\" } 2020-06-17 15:42:56.328 | INFO | httprunner.client:request:203 - status_code: 200, response_time(ms): 1307.33 ms, response_length: 477 bytes 2020-06-17 15:42:56.328 | INFO | httprunner.response:extract:152 - extract mapping: {'foo3': 'bar21'} 2020-06-17 15:42:56.328 | INFO | httprunner.response:validate:209 - assert status_code equal 200(int) ==> pass 2020-06-17 15:42:56.329 | INFO | httprunner.response:validate:209 - assert body.args.foo1 equal bar11(str) ==> pass 2020-06-17 15:42:56.329 | INFO | httprunner.response:validate:209 - assert body.args.sum_v equal 3(str) ==> pass 2020-06-17 15:42:56.329 | INFO | httprunner.response:validate:209 - assert body.args.foo2 equal bar21(str) ==> pass 2020-06-17 15:42:56.330 | INFO | httprunner.runner:__run_step:290 - run step end: get with params <<<<<< 2020-06-17 15:42:57.019 | INFO | httprunner.runner:test_start:444 - generate testcase log: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/logs/cc404c49-000f-485c-b4c1-ac3367a053fe.run.log . ======================================================================= 1 passed in 2.13s ======================================================================= Also, an execution log file will be generated for each testcase, located in /logs/TestCaseID.run.log .","title":"execution logs"},{"location":"user/run_testcase/#testcase-id-request-id","text":"For the sake of troubleshooting, each testcase will generate a unique ID (uuid4), and each request headers will be added a HRUN-Request-ID field with testcase ID automatically. HRUN-Request-ID = \"HRUN--\" timestamp_six_digits = str(int(time.time() * 1000))[-6:]) In other words, all requests in one testcase will have the same HRUN-Request-ID prefix, and each request will have a unique HRUN-Request-ID suffix.","title":"TestCase ID & Request ID"},{"location":"user/run_testcase/#arguments-for-v2x-compatibility","text":"Besides all the arguments of pytest , hrun also has several other arguments to keep compatibility with HttpRunner v2.x. --failfast : has no effect, this argument will be removed automatically --report-file : specify html report file path, this argument will be replaced with --html --self-contained-html and generate html report with pytest-html plugin --save-tests : if set, HttpRunner v3.x will create a pytest conftest.py file containing session fixture to aggregate each testcase's summary and dumps to summary.json","title":"arguments for v2.x compatibility"},{"location":"user/scaffold/","text":"Scaffold \u00b6 If you want to create a new project, you can use the scaffold to startup quickly. help \u00b6 $ httprunner startproject -h usage: httprunner startproject [-h] [project_name] positional arguments: project_name Specify new project name. optional arguments: -h, --help show this help message and exit create new project \u00b6 The only argument you need to specify is the project name. $ httprunner startproject demo 2020-06-15 11:53:25.498 | INFO | httprunner.scaffold:create_scaffold:37 - Create new project: demo Project Root Dir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo created folder: demo created folder: demo/har created folder: demo/testcases created folder: demo/reports created file: demo/testcases/demo_testcase_request.yml created file: demo/testcases/demo_testcase_ref.yml created file: demo/debugtalk.py created file: demo/.env created file: demo/.gitignore $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files If you specify a project name that already exists, you will get a warning. $ httprunner startproject demo 2020-06-15 11:55:03.192 | WARNING | httprunner.scaffold:create_scaffold:32 - Project demo exists, please specify a new project name. $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files run scaffold project \u00b6 The scaffold project has several valid testcases, so you can run tests without any edit. $ hrun demo 2020-06-15 11:57:15.883 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/.env 2020-06-15 11:57:15.883 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 11:57:15.884 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 11:57:15.885 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref.yml 2020-06-15 11:57:15.898 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.899 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py 2020-06-15 11:57:15.900 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py 2020-06-15 11:57:15.911 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.912 | INFO | httprunner.make:__ensure_project_meta_files:128 - copy .env to /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/_env 2020-06-15 11:57:15.912 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py All done! \u2728 \ud83c\udf70 \u2728 2 files reformatted, 1 file left unchanged. 2020-06-15 11:57:16.299 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 2 items demo/testcases/demo_testcase_request_test.py . [ 50%] demo/testcases/demo_testcase_ref_test.py . [100%] ======================================================================= 2 passed in 6.87s =======================================================================","title":"Scaffold"},{"location":"user/scaffold/#scaffold","text":"If you want to create a new project, you can use the scaffold to startup quickly.","title":"Scaffold"},{"location":"user/scaffold/#help","text":"$ httprunner startproject -h usage: httprunner startproject [-h] [project_name] positional arguments: project_name Specify new project name. optional arguments: -h, --help show this help message and exit","title":"help"},{"location":"user/scaffold/#create-new-project","text":"The only argument you need to specify is the project name. $ httprunner startproject demo 2020-06-15 11:53:25.498 | INFO | httprunner.scaffold:create_scaffold:37 - Create new project: demo Project Root Dir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo created folder: demo created folder: demo/har created folder: demo/testcases created folder: demo/reports created file: demo/testcases/demo_testcase_request.yml created file: demo/testcases/demo_testcase_ref.yml created file: demo/debugtalk.py created file: demo/.env created file: demo/.gitignore $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files If you specify a project name that already exists, you will get a warning. $ httprunner startproject demo 2020-06-15 11:55:03.192 | WARNING | httprunner.scaffold:create_scaffold:32 - Project demo exists, please specify a new project name. $ tree demo -a demo \u251c\u2500\u2500 .env \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 debugtalk.py \u251c\u2500\u2500 har \u251c\u2500\u2500 reports \u2514\u2500\u2500 testcases \u251c\u2500\u2500 demo_testcase_ref.yml \u2514\u2500\u2500 demo_testcase_request.yml 3 directories, 5 files","title":"create new project"},{"location":"user/scaffold/#run-scaffold-project","text":"The scaffold project has several valid testcases, so you can run tests without any edit. $ hrun demo 2020-06-15 11:57:15.883 | INFO | httprunner.loader:load_dot_env_file:130 - Loading environment variables from /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/.env 2020-06-15 11:57:15.883 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: USERNAME 2020-06-15 11:57:15.884 | DEBUG | httprunner.utils:set_os_environ:32 - Set OS environment variable: PASSWORD 2020-06-15 11:57:15.885 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref.yml 2020-06-15 11:57:15.898 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.899 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py 2020-06-15 11:57:15.900 | INFO | httprunner.make:make_testcase:383 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py 2020-06-15 11:57:15.911 | INFO | httprunner.make:make_testcase:310 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request.yml 2020-06-15 11:57:15.912 | INFO | httprunner.make:__ensure_project_meta_files:128 - copy .env to /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/_env 2020-06-15 11:57:15.912 | INFO | httprunner.make:format_pytest_with_black:147 - format pytest cases with black ... reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_ref_test.py reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/demo/testcases/demo_testcase_request_test.py All done! \u2728 \ud83c\udf70 \u2728 2 files reformatted, 1 file left unchanged. 2020-06-15 11:57:16.299 | INFO | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.12 ====================================================================== test session starts ====================================================================== platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1 rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1 collected 2 items demo/testcases/demo_testcase_request_test.py . [ 50%] demo/testcases/demo_testcase_ref_test.py . [100%] ======================================================================= 2 passed in 6.87s =======================================================================","title":"run scaffold project"},{"location":"user/testing_report/","text":"Testing Report \u00b6 Benefit from the integration of pytest , HttpRunner v3.x can make use of all the pytest plugins, including testing report plugins like pytest-html and allure-pytest . builtin html report \u00b6 pytest-html plugin comes with HttpRunner installation. When you want to generate a html report for testcase execution, you can add a command argument --html . $ hrun /path/to/testcase --html=report.html If you want to create a self-contained report, which is a single HTML file that can be more convenient when sharing results, you can add another command argument --self-contained-html . $ hrun /path/to/testcase --html=report.html --self-contained-html You can refer to pytest-html for more details. allure report \u00b6 allure-pytest is an optional dependency for HttpRunner, thus if you want to generate allure report, you should install allure-pytest plugin separately. $ pip3 install \"allure-pytest\" Or you can install HttpRunner with allure extra package. $ pip3 install \"httprunner[allure]\" Once allure-pytest is ready, the following arguments can be used with hrun/pytest command. --alluredir=DIR : Generate Allure report in the specified directory (may not exist) --clean-alluredir : Clean alluredir folder if it exists --allure-no-capture : Do not attach pytest captured logging/stdout/stderr to report To enable Allure listener to collect results during the test execution simply add --alluredir option and provide path to the folder where results should be stored. E.g.: $ hrun /path/to/testcase --alluredir=/tmp/my_allure_results To see the actual report after your tests have finished, you need to use Allure commandline utility to generate report from the results. $ allure serve /tmp/my_allure_results This command will show you generated report in your default browser. You can refer to allure-pytest for more details.","title":"Testing Report"},{"location":"user/testing_report/#testing-report","text":"Benefit from the integration of pytest , HttpRunner v3.x can make use of all the pytest plugins, including testing report plugins like pytest-html and allure-pytest .","title":"Testing Report"},{"location":"user/testing_report/#builtin-html-report","text":"pytest-html plugin comes with HttpRunner installation. When you want to generate a html report for testcase execution, you can add a command argument --html . $ hrun /path/to/testcase --html=report.html If you want to create a self-contained report, which is a single HTML file that can be more convenient when sharing results, you can add another command argument --self-contained-html . $ hrun /path/to/testcase --html=report.html --self-contained-html You can refer to pytest-html for more details.","title":"builtin html report"},{"location":"user/testing_report/#allure-report","text":"allure-pytest is an optional dependency for HttpRunner, thus if you want to generate allure report, you should install allure-pytest plugin separately. $ pip3 install \"allure-pytest\" Or you can install HttpRunner with allure extra package. $ pip3 install \"httprunner[allure]\" Once allure-pytest is ready, the following arguments can be used with hrun/pytest command. --alluredir=DIR : Generate Allure report in the specified directory (may not exist) --clean-alluredir : Clean alluredir folder if it exists --allure-no-capture : Do not attach pytest captured logging/stdout/stderr to report To enable Allure listener to collect results during the test execution simply add --alluredir option and provide path to the folder where results should be stored. E.g.: $ hrun /path/to/testcase --alluredir=/tmp/my_allure_results To see the actual report after your tests have finished, you need to use Allure commandline utility to generate report from the results. $ allure serve /tmp/my_allure_results This command will show you generated report in your default browser. You can refer to allure-pytest for more details.","title":"allure report"},{"location":"user/write_testcase/","text":"Write Testcase \u00b6 HttpRunner v3.x supports three testcase formats, pytest , YAML and JSON . It is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. The format relations are illustrated as below: record & generate testcase \u00b6 If the SUT (system under test) is ready, the most efficient way is to capture HTTP traffic first and then generate testcases with HAR file. Refer to Record & Generate testcase for more details. Based on the generated pytest testcase, you can then do some adjustment as needed, thus you need to know the details of testcase format. testcase structure \u00b6 Each testcase is a subclass of HttpRunner , and must have two class attributes: config and teststeps . config: configure testcase level settings, including base_url , verify , variables , export . teststeps: list of teststep ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Besides, variables / extract / validate / hooks mechanisms are supported to create extremely complex test scenarios. from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCaseRequestWithFunctions ( HttpRunner ): config = ( Config ( \"request methods testcase with functions\" ) . variables ( ** { \"foo1\" : \"config_bar1\" , \"foo2\" : \"config_bar2\" , \"expect_foo1\" : \"config_bar1\" , \"expect_foo2\" : \"config_bar2\" , } ) . base_url ( \"https://postman-echo.com\" ) . verify ( False ) . export ( * [ \"foo3\" ]) ) teststeps = [ Step ( RunRequest ( \"get with params\" ) . with_variables ( ** { \"foo1\" : \"bar11\" , \"foo2\" : \"bar21\" , \"sum_v\" : \"${sum_two(1, 2)}\" } ) . get ( \"/get\" ) . with_params ( ** { \"foo1\" : \"$foo1\" , \"foo2\" : \"$foo2\" , \"sum_v\" : \"$sum_v\" }) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" }) . extract () . with_jmespath ( \"body.args.foo2\" , \"foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.args.foo1\" , \"bar11\" ) . assert_equal ( \"body.args.sum_v\" , \"3\" ) . assert_equal ( \"body.args.foo2\" , \"bar21\" ) ), Step ( RunRequest ( \"post form data\" ) . with_variables ( ** { \"foo2\" : \"bar23\" }) . post ( \"/post\" ) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , } ) . with_data ( \"foo1=$foo1&foo2=$foo2&foo3=$foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.form.foo1\" , \"$expect_foo1\" ) . assert_equal ( \"body.form.foo2\" , \"bar23\" ) . assert_equal ( \"body.form.foo3\" , \"bar21\" ) ), ] if __name__ == \"__main__\" : TestCaseRequestWithFunctions () . test_start () chain call \u00b6 One of the most awesome features of HttpRunner v3.x is chain call , with which you do not need to remember any testcase format details and you can get intelligent completion when you write testcases in IDE. config \u00b6 Each testcase should have one config part, in which you can configure testcase level settings. name (required) \u00b6 Specify testcase name. This will be displayed in execution log and test report. base_url (optional) \u00b6 Specify common schema and host part of the SUT, e.g. https://postman-echo.com . If base_url is specified, url in teststep can only set relative path part. This is especially useful if you want to switch between different SUT environments. variables (optional) \u00b6 Specify common variables of testcase. Each teststep can reference config variable which is not set in step variables. In other words, step variables have higher priority than config variables. verify (optional) \u00b6 Specify whether to verify the server\u2019s TLS certificate. This is especially useful if we want to record HTTP traffic of testcase execution, because SSLError will be occurred if verify is not set or been set to True. SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)')) export (optional) \u00b6 Specify the exported session variables of testcase. Consider each testcase as a black box, config variables is the input part, and config export is the output part. In particular, when a testcase is referenced in another testcase's step, and will be extracted some session variables to be used in subsequent teststeps, then the extracted session variables should be configured in config export part. teststeps \u00b6 Each testcase should have one or multiple ordered test steps ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Notice: The concept of API in HttpRunner v2.x has been deprecated for simplification. You can consider API as a testcase that has only one request step. RunRequest(name) \u00b6 RunRequest is used in a step to make request to API and do some extraction or validations for response. The argument name of RunRequest is used to specify teststep name, which will be displayed in execution log and test report. .with_variables \u00b6 Specify teststep variables. The variables of each step are independent, thus if you want to share variables in multiple steps, you should define variables in config variables. Besides, the step variables will override the ones that have the same name in config variables. .method(url) \u00b6 Specify HTTP method and the url of SUT. These are corresponding to method and url arguments of requests.request . If base_url is set in config, url can only set relative path part. .with_params \u00b6 Specify query string for the request url. This is corresponding to the params argument of requests.request . .with_headers \u00b6 Specify HTTP headers for the request. This is corresponding to the headers argument of requests.request . .with_cookies \u00b6 Specify HTTP request cookies. This is corresponding to the cookies argument of requests.request . .with_data \u00b6 Specify HTTP request body. This is corresponding to the data argument of requests.request . .with_json \u00b6 Specify HTTP request body in json. This is corresponding to the json argument of requests.request . extract \u00b6 .with_jmespath \u00b6 Extract JSON response body with jmespath . with_jmespath(jmes_path: Text, var_name: Text) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details var_name: the variable name that stores extracted value, it can be referenced by subsequent test steps validate \u00b6 .assert_XXX \u00b6 Extract JSON response body with jmespath and validate with expected value. assert_XXX(jmes_path: Text, expected_value: Any) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details expected_value: the specified expected value, variable or function reference can also be used here The image below shows HttpRunner builtin validators. RunTestCase(name) \u00b6 RunTestCase is used in a step to reference another testcase call. The argument name of RunTestCase is used to specify teststep name, which will be displayed in execution log and test report. .with_variables \u00b6 Same with RunRequest's .with_variables . .call \u00b6 Specify referenced testcase class. .export \u00b6 Specify session variable names to export from referenced testcase. The exported variables can be referenced by subsequent test steps. import os import sys sys . path . insert ( 0 , os . getcwd ()) from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase from examples.postman_echo.request_methods.request_with_functions_test import ( TestCaseRequestWithFunctions as RequestWithFunctions , ) class TestCaseRequestWithTestcaseReference ( HttpRunner ): config = ( Config ( \"request methods testcase: reference testcase\" ) . variables ( ** { \"foo1\" : \"testsuite_config_bar1\" , \"expect_foo1\" : \"testsuite_config_bar1\" , \"expect_foo2\" : \"config_bar2\" , } ) . base_url ( \"https://postman-echo.com\" ) . verify ( False ) ) teststeps = [ Step ( RunTestCase ( \"request with functions\" ) . with_variables ( ** { \"foo1\" : \"testcase_ref_bar1\" , \"expect_foo1\" : \"testcase_ref_bar1\" } ) . call ( RequestWithFunctions ) . export ( * [ \"foo3\" ]) ), Step ( RunRequest ( \"post form data\" ) . with_variables ( ** { \"foo1\" : \"bar1\" }) . post ( \"/post\" ) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , } ) . with_data ( \"foo1=$foo1&foo2=$foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.form.foo1\" , \"bar1\" ) . assert_equal ( \"body.form.foo2\" , \"bar21\" ) ), ] if __name__ == \"__main__\" : TestCaseRequestWithTestcaseReference () . test_start ()","title":"Write Testcase"},{"location":"user/write_testcase/#write-testcase","text":"HttpRunner v3.x supports three testcase formats, pytest , YAML and JSON . It is extremely recommended to write and maintain testcases in pytest format instead of former YAML/JSON format. The format relations are illustrated as below:","title":"Write Testcase"},{"location":"user/write_testcase/#record-generate-testcase","text":"If the SUT (system under test) is ready, the most efficient way is to capture HTTP traffic first and then generate testcases with HAR file. Refer to Record & Generate testcase for more details. Based on the generated pytest testcase, you can then do some adjustment as needed, thus you need to know the details of testcase format.","title":"record & generate testcase"},{"location":"user/write_testcase/#testcase-structure","text":"Each testcase is a subclass of HttpRunner , and must have two class attributes: config and teststeps . config: configure testcase level settings, including base_url , verify , variables , export . teststeps: list of teststep ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Besides, variables / extract / validate / hooks mechanisms are supported to create extremely complex test scenarios. from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase class TestCaseRequestWithFunctions ( HttpRunner ): config = ( Config ( \"request methods testcase with functions\" ) . variables ( ** { \"foo1\" : \"config_bar1\" , \"foo2\" : \"config_bar2\" , \"expect_foo1\" : \"config_bar1\" , \"expect_foo2\" : \"config_bar2\" , } ) . base_url ( \"https://postman-echo.com\" ) . verify ( False ) . export ( * [ \"foo3\" ]) ) teststeps = [ Step ( RunRequest ( \"get with params\" ) . with_variables ( ** { \"foo1\" : \"bar11\" , \"foo2\" : \"bar21\" , \"sum_v\" : \"${sum_two(1, 2)}\" } ) . get ( \"/get\" ) . with_params ( ** { \"foo1\" : \"$foo1\" , \"foo2\" : \"$foo2\" , \"sum_v\" : \"$sum_v\" }) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" }) . extract () . with_jmespath ( \"body.args.foo2\" , \"foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.args.foo1\" , \"bar11\" ) . assert_equal ( \"body.args.sum_v\" , \"3\" ) . assert_equal ( \"body.args.foo2\" , \"bar21\" ) ), Step ( RunRequest ( \"post form data\" ) . with_variables ( ** { \"foo2\" : \"bar23\" }) . post ( \"/post\" ) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , } ) . with_data ( \"foo1=$foo1&foo2=$foo2&foo3=$foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.form.foo1\" , \"$expect_foo1\" ) . assert_equal ( \"body.form.foo2\" , \"bar23\" ) . assert_equal ( \"body.form.foo3\" , \"bar21\" ) ), ] if __name__ == \"__main__\" : TestCaseRequestWithFunctions () . test_start ()","title":"testcase structure"},{"location":"user/write_testcase/#chain-call","text":"One of the most awesome features of HttpRunner v3.x is chain call , with which you do not need to remember any testcase format details and you can get intelligent completion when you write testcases in IDE.","title":"chain call"},{"location":"user/write_testcase/#config","text":"Each testcase should have one config part, in which you can configure testcase level settings.","title":"config"},{"location":"user/write_testcase/#name-required","text":"Specify testcase name. This will be displayed in execution log and test report.","title":"name (required)"},{"location":"user/write_testcase/#base_url-optional","text":"Specify common schema and host part of the SUT, e.g. https://postman-echo.com . If base_url is specified, url in teststep can only set relative path part. This is especially useful if you want to switch between different SUT environments.","title":"base_url (optional)"},{"location":"user/write_testcase/#variables-optional","text":"Specify common variables of testcase. Each teststep can reference config variable which is not set in step variables. In other words, step variables have higher priority than config variables.","title":"variables (optional)"},{"location":"user/write_testcase/#verify-optional","text":"Specify whether to verify the server\u2019s TLS certificate. This is especially useful if we want to record HTTP traffic of testcase execution, because SSLError will be occurred if verify is not set or been set to True. SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1076)'))","title":"verify (optional)"},{"location":"user/write_testcase/#export-optional","text":"Specify the exported session variables of testcase. Consider each testcase as a black box, config variables is the input part, and config export is the output part. In particular, when a testcase is referenced in another testcase's step, and will be extracted some session variables to be used in subsequent teststeps, then the extracted session variables should be configured in config export part.","title":"export (optional)"},{"location":"user/write_testcase/#teststeps","text":"Each testcase should have one or multiple ordered test steps ( List[Step] ), each step is corresponding to a API request or another testcase reference call. Notice: The concept of API in HttpRunner v2.x has been deprecated for simplification. You can consider API as a testcase that has only one request step.","title":"teststeps"},{"location":"user/write_testcase/#runrequestname","text":"RunRequest is used in a step to make request to API and do some extraction or validations for response. The argument name of RunRequest is used to specify teststep name, which will be displayed in execution log and test report.","title":"RunRequest(name)"},{"location":"user/write_testcase/#with_variables","text":"Specify teststep variables. The variables of each step are independent, thus if you want to share variables in multiple steps, you should define variables in config variables. Besides, the step variables will override the ones that have the same name in config variables.","title":".with_variables"},{"location":"user/write_testcase/#methodurl","text":"Specify HTTP method and the url of SUT. These are corresponding to method and url arguments of requests.request . If base_url is set in config, url can only set relative path part.","title":".method(url)"},{"location":"user/write_testcase/#with_params","text":"Specify query string for the request url. This is corresponding to the params argument of requests.request .","title":".with_params"},{"location":"user/write_testcase/#with_headers","text":"Specify HTTP headers for the request. This is corresponding to the headers argument of requests.request .","title":".with_headers"},{"location":"user/write_testcase/#with_cookies","text":"Specify HTTP request cookies. This is corresponding to the cookies argument of requests.request .","title":".with_cookies"},{"location":"user/write_testcase/#with_data","text":"Specify HTTP request body. This is corresponding to the data argument of requests.request .","title":".with_data"},{"location":"user/write_testcase/#with_json","text":"Specify HTTP request body in json. This is corresponding to the json argument of requests.request .","title":".with_json"},{"location":"user/write_testcase/#extract","text":"","title":"extract"},{"location":"user/write_testcase/#with_jmespath","text":"Extract JSON response body with jmespath . with_jmespath(jmes_path: Text, var_name: Text) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details var_name: the variable name that stores extracted value, it can be referenced by subsequent test steps","title":".with_jmespath"},{"location":"user/write_testcase/#validate","text":"","title":"validate"},{"location":"user/write_testcase/#assert_xxx","text":"Extract JSON response body with jmespath and validate with expected value. assert_XXX(jmes_path: Text, expected_value: Any) jmes_path: jmespath expression, refer to JMESPath Tutorial for more details expected_value: the specified expected value, variable or function reference can also be used here The image below shows HttpRunner builtin validators.","title":".assert_XXX"},{"location":"user/write_testcase/#runtestcasename","text":"RunTestCase is used in a step to reference another testcase call. The argument name of RunTestCase is used to specify teststep name, which will be displayed in execution log and test report.","title":"RunTestCase(name)"},{"location":"user/write_testcase/#with_variables_1","text":"Same with RunRequest's .with_variables .","title":".with_variables"},{"location":"user/write_testcase/#call","text":"Specify referenced testcase class.","title":".call"},{"location":"user/write_testcase/#export","text":"Specify session variable names to export from referenced testcase. The exported variables can be referenced by subsequent test steps. import os import sys sys . path . insert ( 0 , os . getcwd ()) from httprunner import HttpRunner , Config , Step , RunRequest , RunTestCase from examples.postman_echo.request_methods.request_with_functions_test import ( TestCaseRequestWithFunctions as RequestWithFunctions , ) class TestCaseRequestWithTestcaseReference ( HttpRunner ): config = ( Config ( \"request methods testcase: reference testcase\" ) . variables ( ** { \"foo1\" : \"testsuite_config_bar1\" , \"expect_foo1\" : \"testsuite_config_bar1\" , \"expect_foo2\" : \"config_bar2\" , } ) . base_url ( \"https://postman-echo.com\" ) . verify ( False ) ) teststeps = [ Step ( RunTestCase ( \"request with functions\" ) . with_variables ( ** { \"foo1\" : \"testcase_ref_bar1\" , \"expect_foo1\" : \"testcase_ref_bar1\" } ) . call ( RequestWithFunctions ) . export ( * [ \"foo3\" ]) ), Step ( RunRequest ( \"post form data\" ) . with_variables ( ** { \"foo1\" : \"bar1\" }) . post ( \"/post\" ) . with_headers ( ** { \"User-Agent\" : \"HttpRunner/${get_httprunner_version()}\" , \"Content-Type\" : \"application/x-www-form-urlencoded\" , } ) . with_data ( \"foo1=$foo1&foo2=$foo3\" ) . validate () . assert_equal ( \"status_code\" , 200 ) . assert_equal ( \"body.form.foo1\" , \"bar1\" ) . assert_equal ( \"body.form.foo2\" , \"bar21\" ) ), ] if __name__ == \"__main__\" : TestCaseRequestWithTestcaseReference () . test_start ()","title":".export"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index ea02234a..1b8061af 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,31 +1,39 @@ None - 2020-06-16 + 2020-06-17 daily None - 2020-06-16 + 2020-06-17 daily None - 2020-06-16 + 2020-06-17 daily None - 2020-06-16 + 2020-06-17 daily None - 2020-06-16 + 2020-06-17 daily None - 2020-06-16 + 2020-06-17 daily None - 2020-06-16 + 2020-06-17 + daily + + None + 2020-06-17 + daily + + None + 2020-06-17 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 4c2e13dc5bfd2fa1e7c61c616d4a1b833805677a..fad7ee58f17f21678d7e12859367cbaf1c48ae12 100644 GIT binary patch literal 200 zcmV;(05|_1iwFp6+v#2c|8r?{Wo=<_E_iKh0PU2&4#FT1hxa}OVJ}BJ_%D=hj!yaj zgknoVp#oZcd%@Ji7jP@fao_ze-*&8hjs`uH58BxVSA=4utaP2WeS + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + @@ -487,7 +511,7 @@ diff --git a/user/gen_tests/index.html b/user/gen_tests/index.html index 2dba1505..b623e943 100644 --- a/user/gen_tests/index.html +++ b/user/gen_tests/index.html @@ -358,6 +358,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/user/run_testcase/index.html b/user/run_testcase/index.html new file mode 100644 index 00000000..9f210342 --- /dev/null +++ b/user/run_testcase/index.html @@ -0,0 +1,1003 @@ + + + + + + + + + + + + + + + + + + + + + + Run Testcase - HttpRunner V3.x Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + 跳转至 + + +
    +
    + +
    + +
    + +
    + +
    + + + + + + +
    +
    + + +
    +
    +
    + +
    +
    +
    + + + + + +
    +
    + + + + + + +

    Run Testcase

    +

    Once testcase is ready, you can run testcase with hrun command.

    +

    Notice, hrun is an command alias of httprunner run, they have the same effect.

    +
    hrun = httprunner run
    +
    + + +

    run testcases in diverse ways

    +

    HttpRunner can run testcases in diverse ways.

    +

    You can run single testcase by specifying testcase file path.

    +
    $ hrun path/to/testcase1
    +
    + + +

    You can also run several testcases by specifying multiple testcase file paths.

    +
    $ hrun path/to/testcase1 path/to/testcase2
    +
    + + +

    If you want to run testcases of a whole project, you can achieve this goal by specifying the project folder path.

    +
    $ hrun path/to/testcase_folder/
    +
    + + +

    run YAML/JSON testcases

    +

    If your testcases are written in YAML/JSON format, hrun will firstly convert YAML/JSON testcases to pytest(python) files, and run with pytest command.

    +

    That is to say,

    +
    hrun = make + pytest
    +
    + + +

    In most cases, the generated pytest files are in the same folder next to origin YAML/JSON files, with the same file name except adding _test suffix and replace extension .yml/yaml/.json with .py.

    +
    /path/to/example.yml => /path/to/example_test.py
    +
    + + +

    However, if the testcase folder name or file name contains symbols like dot, hyphen or space, these symbols will be replaced with underscore in order to avoid syntax error in python class importing (testcase reference). Also, folder/file name starts with digit will be adding a prefix T because python module and class name can not be started with digit.

    +
    path 1/a.b-2/3.yml => path_1/a_b_2/T3_test.py
    +
    + + +

    run pytest testcases

    +

    If your testcases are written in pytest format, or you want to run pytest files converted from YAML/JSON testcases, hrun and pytest commands are both okay. What you need to remember is that hrun only wraps pytest, thus all the arguments of pytest can be used with hrun.

    +
    $ 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
    +  --import-mode={prepend,append}
    +                        prepend/append to sys.path when importing test modules, default is to prepend.
    +  --pdb                 start the interactive Python debugger on errors or KeyboardInterrupt.
    +  --pdbcls=modulename:classname
    +                        start a custom interactive Python debugger on errors. For example: --pdbcls=IPython.terminal.debugger:TerminalPdb
    +  --trace               Immediately break when running each test.
    +  --capture=method      per-test capturing method: one of fd|sys|no|tee-sys.
    +  -s                    shortcut for --capture=no.
    +  --runxfail            report the results of xfail tests as if they were not marked
    +  --lf, --last-failed   rerun only the tests that failed at the last run (or all if none failed)
    +  --ff, --failed-first  run all tests but run the last failures first. This may re-order tests and thus lead to repeated fixture setup/teardown
    +  --nf, --new-first     run tests from new files first, then the rest of the tests sorted by file mtime
    +  --cache-show=[CACHESHOW]
    +                        show cache contents, don't perform collection or tests. Optional argument: glob (default: '*').
    +  --cache-clear         remove all cache contents at start of test run.
    +  --lfnf={all,none}, --last-failed-no-failures={all,none}
    +                        which tests to run with no previously (known) failures.
    +  --sw, --stepwise      exit on test failure and continue from last failing test next time
    +  --stepwise-skip       ignore the first failing test but stop on the next failing test
    +  --allure-severities=SEVERITIES_SET
    +                        Comma-separated list of severity names. Tests only with these severities will be run. Possible values are: blocker, critical, normal,
    +                        minor, trivial.
    +  --allure-epics=EPICS_SET
    +                        Comma-separated list of epic names. Run tests that have at least one of the specified feature labels.
    +  --allure-features=FEATURES_SET
    +                        Comma-separated list of feature names. Run tests that have at least one of the specified feature labels.
    +  --allure-stories=STORIES_SET
    +                        Comma-separated list of story names. Run tests that have at least one of the specified story labels.
    +  --allure-link-pattern=LINK_TYPE:LINK_PATTERN
    +                        Url pattern for link type. Allows short links in test, like 'issue-1'. Text will be formatted to full url with python str.format().
    +
    +reporting:
    +  --durations=N         show N slowest setup/test durations (N=0 for all).
    +  -v, --verbose         increase verbosity.
    +  -q, --quiet           decrease verbosity.
    +  --verbosity=VERBOSE   set verbosity. Default is 0.
    +  -r chars              show extra test summary info as specified by chars: (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output,
    +                        (a)ll except passed (p/P), or (A)ll. (w)arnings are enabled by default (see --disable-warnings), 'N' can be used to reset the list.
    +                        (default: 'fE').
    +  --disable-warnings, --disable-pytest-warnings
    +                        disable warnings summary
    +  -l, --showlocals      show locals in tracebacks (disabled by default).
    +  --tb=style            traceback print mode (auto/long/short/line/native/no).
    +  --show-capture={no,stdout,stderr,log,all}
    +                        Controls how captured stdout/stderr/log is shown on failed tests. Default is 'all'.
    +  --full-trace          don't cut any tracebacks (default is to cut).
    +  --color=color         color terminal output (yes/no/auto).
    +  --pastebin=mode       send failed|all info to bpaste.net pastebin service.
    +  --junit-xml=path      create junit-xml style report file at given path.
    +  --junit-prefix=str    prepend prefix to classnames in junit-xml output
    +  --result-log=path     DEPRECATED path for machine-readable result log.
    +  --html=path           create html report file at given path.
    +  --self-contained-html
    +                        create a self-contained html file containing all necessary styles, scripts, and images - this means that the report may not render or
    +                        function where CSP restrictions are in place (see https://developer.mozilla.org/docs/Web/Security/CSP)
    +  --css=path            append given css file content to report style file.
    +
    +collection:
    +  --collect-only, --co  only collect tests, don't execute them.
    +  --pyargs              try to interpret all arguments as python packages.
    +  --ignore=path         ignore path during collection (multi-allowed).
    +  --ignore-glob=path    ignore path pattern during collection (multi-allowed).
    +  --deselect=nodeid_prefix
    +                        deselect item (via node id prefix) during collection (multi-allowed).
    +  --confcutdir=dir      only load conftest.py's relative to specified dir.
    +  --noconftest          Don't load any conftest.py files.
    +  --keep-duplicates     Keep duplicate tests.
    +  --collect-in-virtualenv
    +                        Don't ignore tests in a local virtualenv directory
    +  --doctest-modules     run doctests in all .py modules
    +  --doctest-report={none,cdiff,ndiff,udiff,only_first_failure}
    +                        choose another output format for diffs on doctest failure
    +  --doctest-glob=pat    doctests file matching pattern, default: test*.txt
    +  --doctest-ignore-import-errors
    +                        ignore doctest ImportErrors
    +  --doctest-continue-on-failure
    +                        for a given doctest, continue to run after the first failure
    +
    +test session debugging and configuration:
    +  --basetemp=dir        base temporary directory for this test run.(warning: this directory is removed if it exists)
    +  -V, --version         display pytest version and information about plugins.
    +  -h, --help            show help message and configuration info
    +  -p name               early-load given plugin module name or entry point (multi-allowed). To avoid loading of plugins, use the `no:` prefix, e.g. `no:doctest`.
    +  --trace-config        trace considerations of conftest.py files.
    +  --debug               store internal tracing debug information in 'pytestdebug.log'.
    +  -o OVERRIDE_INI, --override-ini=OVERRIDE_INI
    +                        override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`.
    +  --assert=MODE         Control assertion debugging tools. 'plain' performs no assertion debugging. 'rewrite' (the default) rewrites assert statements in test
    +                        modules on import to provide assert expression information.
    +  --setup-only          only setup fixtures, do not execute tests.
    +  --setup-show          show setup of fixtures while executing tests.
    +  --setup-plan          show what fixtures and tests would be executed but don't execute anything.
    +
    +pytest-warnings:
    +  -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS
    +                        set which warnings to report, see -W option of python itself.
    +
    +logging:
    +  --no-print-logs       disable printing caught logs on failed tests.
    +  --log-level=LEVEL     level of messages to catch/display. Not set by default, so it depends on the root/parent log handler's effective level, where it is
    +                        "WARNING" by default.
    +  --log-format=LOG_FORMAT
    +                        log format as used by the logging module.
    +  --log-date-format=LOG_DATE_FORMAT
    +                        log date format as used by the logging module.
    +  --log-cli-level=LOG_CLI_LEVEL
    +                        cli logging level.
    +  --log-cli-format=LOG_CLI_FORMAT
    +                        log format as used by the logging module.
    +  --log-cli-date-format=LOG_CLI_DATE_FORMAT
    +                        log date format as used by the logging module.
    +  --log-file=LOG_FILE   path to a file when logging will be written to.
    +  --log-file-level=LOG_FILE_LEVEL
    +                        log file logging level.
    +  --log-file-format=LOG_FILE_FORMAT
    +                        log format as used by the logging module.
    +  --log-file-date-format=LOG_FILE_DATE_FORMAT
    +                        log date format as used by the logging module.
    +  --log-auto-indent=LOG_AUTO_INDENT
    +                        Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer.
    +
    +reporting:
    +  --alluredir=DIR       Generate Allure report in the specified directory (may not exist)
    +  --clean-alluredir     Clean alluredir folder if it exists
    +  --allure-no-capture   Do not attach pytest captured logging/stdout/stderr to report
    +
    +custom options:
    +  --metadata=key value  additional metadata.
    +  --metadata-from-json=METADATA_FROM_JSON
    +                        additional metadata from a json string.
    +
    +[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:
    +
    +  markers (linelist):   markers for test functions
    +  empty_parameter_set_mark (string):
    +                        default marker for empty parametersets
    +  norecursedirs (args): directory patterns to avoid for recursion
    +  testpaths (args):     directories to search for tests when no files or directories are given in the command line.
    +  usefixtures (args):   list of default fixtures to be used with this project
    +  python_files (args):  glob-style file patterns for Python test module discovery
    +  python_classes (args):
    +                        prefixes or glob names for Python test class discovery
    +  python_functions (args):
    +                        prefixes or glob names for Python test function and method discovery
    +  disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool):
    +                        disable string escape non-ascii characters, might cause unwanted side effects(use at your own risk)
    +  console_output_style (string):
    +                        console output: "classic", or with additional progress information ("progress" (percentage) | "count").
    +  xfail_strict (bool):  default for the strict parameter of xfail markers when not given explicitly (default: False)
    +  enable_assertion_pass_hook (bool):
    +                        Enables the pytest_assertion_pass hook.Make sure to delete any previously generated pyc cache files.
    +  junit_suite_name (string):
    +                        Test suite name for JUnit report
    +  junit_logging (string):
    +                        Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|all
    +  junit_log_passing_tests (bool):
    +                        Capture log information for passing tests to JUnit report:
    +  junit_duration_report (string):
    +                        Duration time to report: one of total|call
    +  junit_family (string):
    +                        Emit XML for schema: one of legacy|xunit1|xunit2
    +  doctest_optionflags (args):
    +                        option flags for doctests
    +  doctest_encoding (string):
    +                        encoding used for doctest files
    +  cache_dir (string):   cache directory path.
    +  filterwarnings (linelist):
    +                        Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings.
    +  log_print (bool):     default value for --no-print-logs
    +  log_level (string):   default value for --log-level
    +  log_format (string):  default value for --log-format
    +  log_date_format (string):
    +                        default value for --log-date-format
    +  log_cli (bool):       enable log display during test run (also known as "live logging").
    +  log_cli_level (string):
    +                        default value for --log-cli-level
    +  log_cli_format (string):
    +                        default value for --log-cli-format
    +  log_cli_date_format (string):
    +                        default value for --log-cli-date-format
    +  log_file (string):    default value for --log-file
    +  log_file_level (string):
    +                        default value for --log-file-level
    +  log_file_format (string):
    +                        default value for --log-file-format
    +  log_file_date_format (string):
    +                        default value for --log-file-date-format
    +  log_auto_indent (string):
    +                        default value for --log-auto-indent
    +  faulthandler_timeout (string):
    +                        Dump the traceback of all threads if a test takes more than TIMEOUT seconds to finish. Not available on Windows.
    +  addopts (args):       extra command line options
    +  minversion (string):  minimally required pytest version
    +  render_collapsed (bool):
    +                        Open the report with all rows collapsed. Useful for very large reports
    +
    +environment variables:
    +  PYTEST_ADDOPTS           extra command line options
    +  PYTEST_PLUGINS           comma-separated plugins to load during startup
    +  PYTEST_DISABLE_PLUGIN_AUTOLOAD set to disable plugin auto-loading
    +  PYTEST_DEBUG             set to enable debug tracing of pytest's internals
    +
    +
    +to see available markers type: pytest --markers
    +to see available fixtures type: pytest --fixtures
    +(shown according to specified file_or_dir or current dir if not specified; fixtures with leading '_' are only shown with the '-v' option
    +
    + + +

    execution logs

    +

    By default, hrun will not print details of request and response data.

    +
    $ hrun examples/postman_echo/request_methods/request_with_functions.yml 
    +2020-06-17 15:39:41.041 | INFO     | httprunner.make:make_testcase:317 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions.yml
    +2020-06-17 15:39:41.042 | INFO     | httprunner.make:make_testcase:390 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py
    +2020-06-17 15:39:41.042 | INFO     | httprunner.make:format_pytest_with_black:154 - format pytest cases with black ...
    +reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py
    +All done! ✨ 🍰 ✨
    +1 file reformatted, 1 file left unchanged.
    +2020-06-17 15:39:41.315 | INFO     | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.13
    +====================================================================== test session starts ======================================================================
    +platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
    +rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner
    +plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1
    +collected 1 item                                                                                                                                                
    +
    +examples/postman_echo/request_methods/request_with_functions_test.py .                                                                                    [100%]
    +
    +======================================================================= 1 passed in 2.98s =======================================================================
    +
    + + +

    If you want to view details of request & response data, extraction and validation, you can add an argument -s (shortcut for --capture=no).

    +
    $ hrun -s examples/postman_echo/request_methods/request_with_functions.yml
    +2020-06-17 15:42:54.369 | INFO     | httprunner.make:make_testcase:317 - start to make testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions.yml
    +2020-06-17 15:42:54.369 | INFO     | httprunner.make:make_testcase:390 - generated testcase: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py
    +2020-06-17 15:42:54.370 | INFO     | httprunner.make:format_pytest_with_black:154 - format pytest cases with black ...
    +reformatted /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/request_methods/request_with_functions_test.py
    +All done! ✨ 🍰 ✨
    +1 file reformatted, 1 file left unchanged.
    +2020-06-17 15:42:54.699 | INFO     | httprunner.cli:main_run:56 - start to run tests with pytest. HttpRunner version: 3.0.13
    +====================================================================== test session starts ======================================================================
    +platform darwin -- Python 3.7.5, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
    +rootdir: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner
    +plugins: metadata-1.9.0, allure-pytest-2.8.16, html-2.1.1
    +collected 1 item                                                                                                                                                
    +
    +examples/postman_echo/request_methods/request_with_functions_test.py 2020-06-17 15:42:55.017 | INFO     | httprunner.runner:test_start:435 - Start to run testcase: request methods testcase with functions, TestCase ID: cc404c49-000f-485c-b4c1-ac3367a053fe
    +2020-06-17 15:42:55.018 | INFO     | httprunner.runner:__run_step:278 - run step begin: get with params >>>>>>
    +2020-06-17 15:42:56.326 | DEBUG    | httprunner.client:log_print:40 - 
    +================== request details ==================
    +method   : GET
    +url      : https://postman-echo.com/get?foo1=bar11&foo2=bar21&sum_v=3
    +headers  : {
    +    "User-Agent": "HttpRunner/3.0.13",
    +    "Accept-Encoding": "gzip, deflate",
    +    "Accept": "*/*",
    +    "Connection": "keep-alive",
    +    "HRUN-Request-ID": "HRUN-cc404c49-000f-485c-b4c1-ac3367a053fe-775018",
    +    "Content-Length": "2",
    +    "Content-Type": "application/json"
    +}
    +cookies  : {}
    +body     : {}
    +
    +2020-06-17 15:42:56.327 | DEBUG    | httprunner.client:log_print:40 - 
    +================== response details ==================
    +status_code : 200
    +headers  : {
    +    "Date": "Wed, 17 Jun 2020 07:42:56 GMT",
    +    "Content-Type": "application/json; charset=utf-8",
    +    "Content-Length": "477",
    +    "Connection": "keep-alive",
    +    "ETag": "W/\"1dd-2JtBYPcnh8D6fqLz8KFn16Oq1R0\"",
    +    "Vary": "Accept-Encoding",
    +    "set-cookie": "sails.sid=s%3A6J_EtUk3nkL_C2xtx-NtAXrlA5wPxEgk.gIO2yBbtvGWIIgQ%2F2mZhMkU669G3F60cvLAPWbwyoGM; Path=/; HttpOnly"
    +}
    +cookies  : {
    +    "sails.sid": "s%3A6J_EtUk3nkL_C2xtx-NtAXrlA5wPxEgk.gIO2yBbtvGWIIgQ%2F2mZhMkU669G3F60cvLAPWbwyoGM"
    +}
    +encoding : utf-8
    +content_type : application/json; charset=utf-8
    +body     : {
    +    "args": {
    +        "foo1": "bar11",
    +        "foo2": "bar21",
    +        "sum_v": "3"
    +    },
    +    "headers": {
    +        "x-forwarded-proto": "https",
    +        "x-forwarded-port": "443",
    +        "host": "postman-echo.com",
    +        "x-amzn-trace-id": "Root=1-5ee9c980-d8e98cc72a26ef24f5819ce3",
    +        "content-length": "2",
    +        "user-agent": "HttpRunner/3.0.13",
    +        "accept-encoding": "gzip, deflate",
    +        "accept": "*/*",
    +        "hrun-request-id": "HRUN-cc404c49-000f-485c-b4c1-ac3367a053fe-775018",
    +        "content-type": "application/json"
    +    },
    +    "url": "https://postman-echo.com/get?foo1=bar11&foo2=bar21&sum_v=3"
    +}
    +
    +2020-06-17 15:42:56.328 | INFO     | httprunner.client:request:203 - status_code: 200, response_time(ms): 1307.33 ms, response_length: 477 bytes
    +2020-06-17 15:42:56.328 | INFO     | httprunner.response:extract:152 - extract mapping: {'foo3': 'bar21'}
    +2020-06-17 15:42:56.328 | INFO     | httprunner.response:validate:209 - assert status_code equal 200(int)       ==> pass
    +2020-06-17 15:42:56.329 | INFO     | httprunner.response:validate:209 - assert body.args.foo1 equal bar11(str)  ==> pass
    +2020-06-17 15:42:56.329 | INFO     | httprunner.response:validate:209 - assert body.args.sum_v equal 3(str)     ==> pass
    +2020-06-17 15:42:56.329 | INFO     | httprunner.response:validate:209 - assert body.args.foo2 equal bar21(str)  ==> pass
    +2020-06-17 15:42:56.330 | INFO     | httprunner.runner:__run_step:290 - run step end: get with params <<<<<<
    +
    +<Omit>
    +
    +2020-06-17 15:42:57.019 | INFO     | httprunner.runner:test_start:444 - generate testcase log: /Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/logs/cc404c49-000f-485c-b4c1-ac3367a053fe.run.log
    +.
    +
    +======================================================================= 1 passed in 2.13s =======================================================================
    +
    + + +

    Also, an execution log file will be generated for each testcase, located in <ProjectRootDir>/logs/TestCaseID.run.log.

    +

    TestCase ID & Request ID

    +

    For the sake of troubleshooting, each testcase will generate a unique ID (uuid4), and each request headers will be added a HRUN-Request-ID field with testcase ID automatically.

    +
    HRUN-Request-ID = "HRUN-<TestCase ID>-<timestamp_six_digits>"
    +timestamp_six_digits = str(int(time.time() * 1000))[-6:])
    +
    + + +

    In other words, all requests in one testcase will have the same HRUN-Request-ID prefix, and each request will have a unique HRUN-Request-ID suffix.

    +

    arguments for v2.x compatibility

    +

    Besides all the arguments of pytest, hrun also has several other arguments to keep compatibility with HttpRunner v2.x.

    +
      +
    • --failfast: has no effect, this argument will be removed automatically
    • +
    • --report-file: specify html report file path, this argument will be replaced with --html --self-contained-html and generate html report with pytest-html plugin
    • +
    • --save-tests: if set, HttpRunner v3.x will create a pytest conftest.py file containing session fixture to aggregate each testcase's summary and dumps to summary.json
    • +
    + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/user/scaffold/index.html b/user/scaffold/index.html index 483431dd..11ed2fed 100644 --- a/user/scaffold/index.html +++ b/user/scaffold/index.html @@ -331,6 +331,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + diff --git a/user/testing_report/index.html b/user/testing_report/index.html new file mode 100644 index 00000000..19edcab7 --- /dev/null +++ b/user/testing_report/index.html @@ -0,0 +1,585 @@ + + + + + + + + + + + + + + + + + + + + + + Testing Report - HttpRunner V3.x Docs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + 跳转至 + + +
    +
    + +
    + +
    + +
    + +
    + + + + + + +
    +
    + + +
    +
    +
    + +
    +
    +
    + + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + +

    Testing Report

    +

    Benefit from the integration of pytest, HttpRunner v3.x can make use of all the pytest plugins, including testing report plugins like pytest-html and allure-pytest.

    +

    builtin html report

    +

    pytest-html plugin comes with HttpRunner installation. When you want to generate a html report for testcase execution, you can add a command argument --html.

    +
    $ hrun /path/to/testcase --html=report.html
    +
    + + +

    If you want to create a self-contained report, which is a single HTML file that can be more convenient when sharing results, you can add another command argument --self-contained-html.

    +
    $ hrun /path/to/testcase --html=report.html --self-contained-html
    +
    + + +

    You can refer to pytest-html for more details.

    +

    allure report

    +

    allure-pytest is an optional dependency for HttpRunner, thus if you want to generate allure report, you should install allure-pytest plugin separately.

    +
    $ pip3 install "allure-pytest"
    +
    + + +

    Or you can install HttpRunner with allure extra package.

    +
    $ pip3 install "httprunner[allure]"
    +
    + + +

    Once allure-pytest is ready, the following arguments can be used with hrun/pytest command.

    +
      +
    • --alluredir=DIR: Generate Allure report in the specified directory (may not exist)
    • +
    • --clean-alluredir: Clean alluredir folder if it exists
    • +
    • --allure-no-capture: Do not attach pytest captured logging/stdout/stderr to report
    • +
    +

    To enable Allure listener to collect results during the test execution simply add --alluredir option and provide path to the folder where results should be stored. E.g.:

    +
    $ hrun /path/to/testcase --alluredir=/tmp/my_allure_results
    +
    + + +

    To see the actual report after your tests have finished, you need to use Allure commandline utility to generate report from the results.

    +
    $ allure serve /tmp/my_allure_results
    +
    + + +

    This command will show you generated report in your default browser.

    +

    You can refer to allure-pytest for more details.

    + + + + + + + +
    +
    +
    +
    + + + + +
    + + + + + + + + + \ No newline at end of file diff --git a/user/write_testcase/index.html b/user/write_testcase/index.html index 19c35d45..491b5d26 100644 --- a/user/write_testcase/index.html +++ b/user/write_testcase/index.html @@ -495,6 +495,20 @@ .with_variables + + +
  • + + .call + + +
  • + +
  • + + .export + +
  • @@ -514,6 +528,30 @@ + + + + + +
  • + + Run Testcase + +
  • + + + + + + + +
  • + + Testing Report + +
  • + + @@ -760,6 +798,20 @@ .with_variables + + +
  • + + .call + + +
  • + +
  • + + .export + +
  • @@ -932,6 +984,67 @@

    The argument name of RunTestCase is used to specify teststep name, which will be displayed in execution log and test report.

    .with_variables

    Same with RunRequest's .with_variables.

    +

    .call

    +

    Specify referenced testcase class.

    +

    .export

    +

    Specify session variable names to export from referenced testcase. The exported variables can be referenced by subsequent test steps.

    +
    import os
    +import sys
    +
    +sys.path.insert(0, os.getcwd())
    +
    +from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
    +
    +from examples.postman_echo.request_methods.request_with_functions_test import (
    +    TestCaseRequestWithFunctions as RequestWithFunctions,
    +)
    +
    +
    +class TestCaseRequestWithTestcaseReference(HttpRunner):
    +    config = (
    +        Config("request methods testcase: reference testcase")
    +        .variables(
    +            **{
    +                "foo1": "testsuite_config_bar1",
    +                "expect_foo1": "testsuite_config_bar1",
    +                "expect_foo2": "config_bar2",
    +            }
    +        )
    +        .base_url("https://postman-echo.com")
    +        .verify(False)
    +    )
    +
    +    teststeps = [
    +        Step(
    +            RunTestCase("request with functions")
    +            .with_variables(
    +                **{"foo1": "testcase_ref_bar1", "expect_foo1": "testcase_ref_bar1"}
    +            )
    +            .call(RequestWithFunctions)
    +            .export(*["foo3"])
    +        ),
    +        Step(
    +            RunRequest("post form data")
    +            .with_variables(**{"foo1": "bar1"})
    +            .post("/post")
    +            .with_headers(
    +                **{
    +                    "User-Agent": "HttpRunner/${get_httprunner_version()}",
    +                    "Content-Type": "application/x-www-form-urlencoded",
    +                }
    +            )
    +            .with_data("foo1=$foo1&foo2=$foo3")
    +            .validate()
    +            .assert_equal("status_code", 200)
    +            .assert_equal("body.form.foo1", "bar1")
    +            .assert_equal("body.form.foo2", "bar21")
    +        ),
    +    ]
    +
    +
    +if __name__ == "__main__":
    +    TestCaseRequestWithTestcaseReference().test_start()
    +
    @@ -965,13 +1078,13 @@ -