mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-05 15:59:33 +08:00
Merge branch 'master' into master
This commit is contained in:
32
.github/workflows/integration_test.yml
vendored
32
.github/workflows/integration_test.yml
vendored
@@ -2,11 +2,8 @@ name: integration_test
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
types: [synchronize]
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
integration_test:
|
integration_test:
|
||||||
@@ -14,32 +11,35 @@ jobs:
|
|||||||
name: integration_test - ${{ matrix.python-version }} on ${{ matrix.os }}
|
name: integration_test - ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
max-parallel: 6
|
max-parallel: 6
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.6, 3.7, 3.8]
|
python-version: ['3.7', '3.8', '3.9', '3.10']
|
||||||
os: [ubuntu-latest, macos-latest] # TODO: windows-latest
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
architecture: x64
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install poetry
|
pip install poetry
|
||||||
poetry --version
|
poetry --version
|
||||||
poetry install -vv -E upload
|
poetry install -vv -E upload
|
||||||
- name: Test package installation
|
- name: Test build package
|
||||||
run: |
|
run: |
|
||||||
poetry build
|
poetry build
|
||||||
ls dist/*.whl | xargs pip install # test installation
|
ls -l dist/
|
||||||
hrun -V
|
- name: Test commands
|
||||||
har2case -h
|
run: |
|
||||||
httprunner run -h
|
poetry run hrun -V
|
||||||
httprunner startproject -h
|
poetry run har2case -h
|
||||||
httprunner har2case -h
|
poetry run httprunner run -h
|
||||||
|
poetry run httprunner startproject -h
|
||||||
|
poetry run httprunner har2case -h
|
||||||
- name: Run smoketest - postman echo
|
- name: Run smoketest - postman echo
|
||||||
run: |
|
run: |
|
||||||
poetry run hrun examples/postman_echo/request_methods
|
poetry run hrun examples/postman_echo/request_methods
|
||||||
|
|||||||
13
.github/workflows/unittest.yml
vendored
13
.github/workflows/unittest.yml
vendored
@@ -2,11 +2,8 @@ name: unittest
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
types: [synchronize]
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
unittest:
|
unittest:
|
||||||
@@ -14,17 +11,19 @@ jobs:
|
|||||||
name: unittest - ${{ matrix.python-version }} on ${{ matrix.os }}
|
name: unittest - ${{ matrix.python-version }} on ${{ matrix.os }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
max-parallel: 12
|
max-parallel: 12
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.6, 3.7, 3.8]
|
python-version: ['3.7', '3.8', '3.9', '3.10']
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v2
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python-version }}
|
python-version: ${{ matrix.python-version }}
|
||||||
|
architecture: x64
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
|
|||||||
67
README.md
67
README.md
@@ -1,67 +0,0 @@
|
|||||||
|
|
||||||
# HttpRunner
|
|
||||||
|
|
||||||
[](https://pepy.tech/project/httprunner)
|
|
||||||
[](https://github.com/httprunner/httprunner/actions)
|
|
||||||
[](https://github.com/httprunner/httprunner/actions)
|
|
||||||
[](https://codecov.io/gh/httprunner/httprunner)
|
|
||||||
[](https://pypi.python.org/pypi/httprunner)
|
|
||||||
[](https://pypi.python.org/pypi/httprunner)
|
|
||||||
[](https://testerhome.com/github_statistics)
|
|
||||||
|
|
||||||
*HttpRunner* is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! ✨ 🚀 ✨
|
|
||||||
|
|
||||||
## Design Philosophy
|
|
||||||
|
|
||||||
- Convention over configuration
|
|
||||||
- ROI matters
|
|
||||||
- Embrace open source, leverage [`requests`][requests], [`pytest`][pytest], [`pydantic`][pydantic], [`allure`][allure] and [`locust`][locust].
|
|
||||||
|
|
||||||
## Key Features
|
|
||||||
|
|
||||||
- Inherit all powerful features of [`requests`][requests], just have fun to handle HTTP(S) in human way.
|
|
||||||
- Define testcase in YAML or JSON format, run with [`pytest`][pytest] in concise and elegant manner.
|
|
||||||
- Record and generate testcases with [`HAR`][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`][jmespath], extract and validate json response has never been easier.
|
|
||||||
- With [`pytest`][pytest], hundreds of plugins are readily available.
|
|
||||||
- With [`allure`][allure], test report can be pretty nice and powerful.
|
|
||||||
- With reuse of [`locust`][locust], you can run performance test without extra work.
|
|
||||||
- CLI command supported, perfect combination with `CI/CD`.
|
|
||||||
|
|
||||||
## Sponsors
|
|
||||||
|
|
||||||
Thank you to all our sponsors! ✨🍰✨ ([become a sponsor](docs/sponsors.md))
|
|
||||||
|
|
||||||
### 金牌赞助商(Gold Sponsor)
|
|
||||||
|
|
||||||
[<img src="docs/assets/hogwarts.png" alt="霍格沃兹测试学院" width="400">](https://ceshiren.com/)
|
|
||||||
|
|
||||||
> [霍格沃兹测试学院](https://ceshiren.com/) 是业界领先的测试开发技术高端教育品牌,隶属于测吧(北京)科技有限公司。学院课程均由 BAT 一线测试大咖执教,提供实战驱动的接口自动化测试、移动自动化测试、性能测试、持续集成与 DevOps 等技术培训,以及测试开发优秀人才内推服务。[点击学习!](https://ke.qq.com/course/254956?flowToken=1014690)
|
|
||||||
|
|
||||||
霍格沃兹测试学院是 HttpRunner 的首家金牌赞助商。
|
|
||||||
|
|
||||||
### 开源服务赞助商(Open Source Sponsor)
|
|
||||||
|
|
||||||
[<img src="docs/assets/sentry-logo-black.svg" alt="Sentry" width="150">](https://sentry.io/_/open-source/)
|
|
||||||
|
|
||||||
HttpRunner is in Sentry Sponsored plan.
|
|
||||||
|
|
||||||
## Subscribe
|
|
||||||
|
|
||||||
关注 HttpRunner 的微信公众号,第一时间获得最新资讯。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[requests]: http://docs.python-requests.org/en/master/
|
|
||||||
[pytest]: https://docs.pytest.org/
|
|
||||||
[pydantic]: https://pydantic-docs.helpmanual.io/
|
|
||||||
[locust]: http://locust.io/
|
|
||||||
[jmespath]: https://jmespath.org/
|
|
||||||
[allure]: https://docs.qameta.io/allure/
|
|
||||||
[HAR]: http://httparchive.org/
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,5 +1,19 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
|
## 3.1.8 (2022-03-22)
|
||||||
|
|
||||||
|
- change: load yaml file with FullLoader
|
||||||
|
|
||||||
|
## 3.1.7 (2022-03-22)
|
||||||
|
|
||||||
|
- fix #1117: ignore comments and blank lines when parsing .env file
|
||||||
|
- fix #1141: parameterize failure caused by pydantic version
|
||||||
|
- fix #1165: ImportError caused by jinja2 version
|
||||||
|
- fix: failure in getting client and server IP/port when requesting HTTPS
|
||||||
|
- fix: upgrade dependencies for security
|
||||||
|
- change: remove support for dead python 3.6, upgrade supported python version to 3.7/3.8/3.9/3.10
|
||||||
|
- change: replace events reporter from sentry to Google Analytics
|
||||||
|
|
||||||
## 3.1.6 (2021-07-18)
|
## 3.1.6 (2021-07-18)
|
||||||
|
|
||||||
**Fixed**
|
**Fixed**
|
||||||
@@ -259,7 +273,7 @@
|
|||||||
|
|
||||||
**Added**
|
**Added**
|
||||||
|
|
||||||
- feat: add `make` sub-command to generate python testcases from YAML/JSON
|
- feat: add `make` sub-command to generate python testcases from YAML/JSON
|
||||||
- feat: format generated python testcases with [`black`](https://github.com/psf/black)
|
- feat: format generated python testcases with [`black`](https://github.com/psf/black)
|
||||||
- test: add postman echo & httpbin as testcase examples
|
- test: add postman echo & httpbin as testcase examples
|
||||||
|
|
||||||
|
|||||||
70
docs/README.md
Normal file
70
docs/README.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
# HttpRunner
|
||||||
|
|
||||||
|
[](https://pepy.tech/project/httprunner)
|
||||||
|
[](https://github.com/httprunner/httprunner/actions)
|
||||||
|
[](https://github.com/httprunner/httprunner/actions)
|
||||||
|
[](https://codecov.io/gh/httprunner/httprunner)
|
||||||
|
[](https://pypi.python.org/pypi/httprunner)
|
||||||
|
[](https://pypi.python.org/pypi/httprunner)
|
||||||
|
[](https://testerhome.com/github_statistics)
|
||||||
|
|
||||||
|
*HttpRunner* is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! ✨ 🚀 ✨
|
||||||
|
|
||||||
|
> 欢迎参加 HttpRunner [用户调研问卷][survey],你的反馈将帮助 HttpRunner 更好地成长!
|
||||||
|
|
||||||
|
## Design Philosophy
|
||||||
|
|
||||||
|
- Convention over configuration
|
||||||
|
- ROI matters
|
||||||
|
- Embrace open source, leverage [`requests`][requests], [`pytest`][pytest], [`pydantic`][pydantic], [`allure`][allure] and [`locust`][locust].
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- [x] Inherit all powerful features of [`requests`][requests], just have fun to handle HTTP(S) in human way.
|
||||||
|
- [x] Define testcase in YAML or JSON format, run with [`pytest`][pytest] in concise and elegant manner.
|
||||||
|
- [x] Record and generate testcases with [`HAR`][HAR] support.
|
||||||
|
- [x] Supports `variables`/`extract`/`validate`/`hooks` mechanisms to create extremely complex test scenarios.
|
||||||
|
- [x] With `debugtalk.py` plugin, any function can be used in any part of your testcase.
|
||||||
|
- [x] With [`jmespath`][jmespath], extract and validate json response has never been easier.
|
||||||
|
- [x] With [`pytest`][pytest], hundreds of plugins are readily available.
|
||||||
|
- [x] With [`allure`][allure], test report can be pretty nice and powerful.
|
||||||
|
- [x] With reuse of [`locust`][locust], you can run performance test without extra work.
|
||||||
|
- [x] CLI command supported, perfect combination with `CI/CD`.
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
Thank you to all our sponsors! ✨🍰✨ ([become a sponsor](sponsors.md))
|
||||||
|
|
||||||
|
### 金牌赞助商(Gold Sponsor)
|
||||||
|
|
||||||
|
[<img src="assets/hogwarts.jpeg" alt="霍格沃兹测试开发学社" width="400">](https://ceshiren.com/)
|
||||||
|
|
||||||
|
> [霍格沃兹测试开发学社](http://qrcode.testing-studio.com/f?from=httprunner&url=https://ceshiren.com)是业界领先的测试开发技术高端教育品牌,隶属于[测吧(北京)科技有限公司](http://qrcode.testing-studio.com/f?from=httprunner&url=https://www.testing-studio.com) 。学院课程由一线大厂测试经理与资深测试开发专家参与研发,实战驱动。课程涵盖 web/app 自动化测试、接口测试、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移&右移、精准测试、测试平台开发、测试管理等内容,帮助测试工程师实现测试开发技术转型。通过优秀的学社制度(奖学金、内推返学费、行业竞赛等多种方式)来实现学员、学社及用人企业的三方共赢。
|
||||||
|
|
||||||
|
> [进入测试开发技术能力测评!](http://qrcode.testing-studio.com/f?from=httprunner&url=https://ceshiren.com/t/topic/14940)
|
||||||
|
|
||||||
|
### 开源服务赞助商(Open Source Sponsor)
|
||||||
|
|
||||||
|
[<img src="assets/sentry-logo-black.svg" alt="Sentry" width="150">](https://sentry.io/_/open-source/)
|
||||||
|
|
||||||
|
HttpRunner is in Sentry Sponsored plan.
|
||||||
|
|
||||||
|
## Subscribe
|
||||||
|
|
||||||
|
关注 HttpRunner 的微信公众号,第一时间获得最新资讯。
|
||||||
|
|
||||||
|
<img src="assets/qrcode.jpg" alt="HttpRunner" width="200">
|
||||||
|
|
||||||
|
如果你期望加入 HttpRunner 核心用户群,请填写[用户调研问卷][survey]并留下你的联系方式,作者将拉你进群。
|
||||||
|
|
||||||
|
[requests]: http://docs.python-requests.org/en/master/
|
||||||
|
[pytest]: https://docs.pytest.org/
|
||||||
|
[pydantic]: https://pydantic-docs.helpmanual.io/
|
||||||
|
[locust]: http://locust.io/
|
||||||
|
[jmespath]: https://jmespath.org/
|
||||||
|
[allure]: https://docs.qameta.io/allure/
|
||||||
|
[HAR]: http://httparchive.org/
|
||||||
|
[survey]: https://wj.qq.com/s2/9699514/0d19/
|
||||||
BIN
docs/assets/hogwarts.jpeg
Normal file
BIN
docs/assets/hogwarts.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.1 KiB |
@@ -1,49 +0,0 @@
|
|||||||
|
|
||||||
# HttpRunner
|
|
||||||
|
|
||||||
[](https://pepy.tech/project/httprunner)
|
|
||||||
[](https://github.com/httprunner/httprunner/actions)
|
|
||||||
[](https://github.com/httprunner/httprunner/actions)
|
|
||||||
[](https://codecov.io/gh/httprunner/httprunner)
|
|
||||||
[](https://pypi.python.org/pypi/httprunner)
|
|
||||||
[](https://pypi.python.org/pypi/httprunner)
|
|
||||||
[](https://testerhome.com/github_statistics)
|
|
||||||
|
|
||||||
*HttpRunner* is a simple & elegant, yet powerful HTTP(S) testing framework. Enjoy! ✨ 🚀 ✨
|
|
||||||
|
|
||||||
> This docs site is corresponding to the latest version `3.x`, for `2.x` you can reference [`archive link`](https://v2.httprunner.org/).
|
|
||||||
|
|
||||||
## Design Philosophy
|
|
||||||
|
|
||||||
- Convention over configuration
|
|
||||||
- ROI matters
|
|
||||||
- Embrace open source, leverage [`requests`][requests], [`pytest`][pytest], [`pydantic`][pydantic], [`allure`][allure] and [`locust`][locust].
|
|
||||||
|
|
||||||
## Key Features
|
|
||||||
|
|
||||||
- Inherit all powerful features of [`requests`][requests], just have fun to handle HTTP(S) in human way.
|
|
||||||
- Define testcase in YAML or JSON format, run with [`pytest`][pytest] in concise and elegant manner.
|
|
||||||
- Record and generate testcases with [`HAR`][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`][jmespath], extract and validate json response has never been easier.
|
|
||||||
- With [`pytest`][pytest], hundreds of plugins are readily available.
|
|
||||||
- With [`allure`][allure], test report can be pretty nice and powerful.
|
|
||||||
- With reuse of [`locust`][locust], you can run performance test without extra work.
|
|
||||||
- CLI command supported, perfect combination with `CI/CD`.
|
|
||||||
|
|
||||||
## Subscribe
|
|
||||||
|
|
||||||
关注 HttpRunner 的微信公众号,第一时间获得最新资讯。
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[requests]: http://docs.python-requests.org/en/master/
|
|
||||||
[pytest]: https://docs.pytest.org/
|
|
||||||
[pydantic]: https://pydantic-docs.helpmanual.io/
|
|
||||||
[locust]: http://locust.io/
|
|
||||||
[jmespath]: https://jmespath.org/
|
|
||||||
[allure]: https://docs.qameta.io/allure/
|
|
||||||
[HAR]: http://httparchive.org/
|
|
||||||
@@ -15,7 +15,7 @@ If you want to keep up with the latest version, you can install with github repo
|
|||||||
$ pip3 install git+https://github.com/httprunner/httprunner.git@master
|
$ pip3 install git+https://github.com/httprunner/httprunner.git@master
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have installed `HttpRunner` before and want to upgrade to the latest version, you can use the `-U` option.
|
If you have installed `HttpRunner` before and want to upgrade to the latest version, you can use the `-U` option.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ pip3 install -U httprunner
|
$ pip3 install -U httprunner
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
## 金牌赞助商(Gold Sponsor)
|
## 金牌赞助商(Gold Sponsor)
|
||||||
|
|
||||||
[<img src="https://docs.httprunner.org/assets/hogwarts.png" alt="霍格沃兹测试学院" width="400">](https://ceshiren.com/)
|
[<img src="https://raw.githubusercontent.com/httprunner/httprunner/master/docs/assets/hogwarts.jpeg" alt="霍格沃兹测试开发学社" width="400">](https://ceshiren.com/)
|
||||||
|
|
||||||
> [霍格沃兹测试学院](https://ceshiren.com/) 是业界领先的测试开发技术高端教育品牌,隶属于测吧(北京)科技有限公司。学院课程均由 BAT 一线测试大咖执教,提供实战驱动的接口自动化测试、移动自动化测试、性能测试、持续集成与 DevOps 等技术培训,以及测试开发优秀人才内推服务。[点击学习!](https://ke.qq.com/course/254956?flowToken=1014690)
|
> [霍格沃兹测试开发学社](http://qrcode.testing-studio.com/f?from=httprunner&url=https://ceshiren.com)是业界领先的测试开发技术高端教育品牌,隶属于[测吧(北京)科技有限公司](http://qrcode.testing-studio.com/f?from=httprunner&url=https://www.testing-studio.com) 。学院课程由一线大厂测试经理与资深测试开发专家参与研发,实战驱动。课程涵盖 web/app 自动化测试、接口测试、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移&右移、精准测试、测试平台开发、测试管理等内容,帮助测试工程师实现测试开发技术转型。通过优秀的学社制度(奖学金、内推返学费、行业竞赛等多种方式)来实现学员、学社及用人企业的三方共赢。
|
||||||
|
|
||||||
[霍格沃兹测试学院](https://ceshiren.com/) 是 HttpRunner 的首家金牌赞助商。
|
> [进入测试开发技术能力测评!](http://qrcode.testing-studio.com/f?from=httprunner&url=https://ceshiren.com/t/topic/14940)
|
||||||
|
|
||||||
### 开源服务赞助商(Open Source Sponsor)
|
### 开源服务赞助商(Open Source Sponsor)
|
||||||
|
|
||||||
@@ -22,5 +22,5 @@ HttpRunner is in Sentry Sponsored plan.
|
|||||||
|
|
||||||
| 等级 | 金牌赞助商<br/>(Gold Sponsor) | 银牌赞助商<br/>(Silver Sponsor)| 个人赞赏 |
|
| 等级 | 金牌赞助商<br/>(Gold Sponsor) | 银牌赞助商<br/>(Silver Sponsor)| 个人赞赏 |
|
||||||
|:---:|:---:|:---:|:---:|
|
|:---:|:---:|:---:|:---:|
|
||||||
| 金额 | ¥10000/年 | ¥5000/年 | 任意 |
|
| 金额 | ¥20000/年 | ¥8000/年 | 任意 |
|
||||||
| 权益 | 公司 logo(大)和链接展示在 README.md<br/>150 字的宣传文案 | 公司 logo(中)和链接展示在 README.md<br/>50 字的宣传文案| 个人 ID 和链接展示在 sponsors.md |
|
| 权益 | 公司 logo(大)和链接展示在 README.md<br/>200 字的宣传文案 | 公司 logo(中)和链接展示在 README.md<br/>80 字的宣传文案| 个人 ID 和链接展示在 sponsors.md |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: basic.yml
|
# FROM: basic.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: hooks.yml
|
# FROM: hooks.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: load_image.yml
|
# FROM: load_image.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: upload.yml
|
# FROM: upload.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: validate.yml
|
# FROM: validate.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ def session_fixture(request):
|
|||||||
testcase_summary_json["records"] = testcase_summary_json.pop("step_datas")
|
testcase_summary_json["records"] = testcase_summary_json.pop("step_datas")
|
||||||
summary["details"].append(testcase_summary_json)
|
summary["details"].append(testcase_summary_json)
|
||||||
|
|
||||||
summary_path = "/Users/debugtalk/MyProjects/HttpRunner-dev/HttpRunner/examples/postman_echo/logs/request_methods/hardcode.summary.json"
|
summary_path = r"/Users/debugtalk/MyProjects/HttpRunner-dev/httprunner/examples/postman_echo/logs/request_methods/hardcode.summary.json"
|
||||||
summary_dir = os.path.dirname(summary_path)
|
summary_dir = os.path.dirname(summary_path)
|
||||||
os.makedirs(summary_dir, exist_ok=True)
|
os.makedirs(summary_dir, exist_ok=True)
|
||||||
|
|
||||||
|
|||||||
1
examples/postman_echo/cookie_manipulation/__init__.py
Normal file
1
examples/postman_echo/cookie_manipulation/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# NOTICE: Generated By HttpRunner. DO NOT EDIT!
|
||||||
@@ -2,7 +2,7 @@ config:
|
|||||||
name: "set & delete cookies."
|
name: "set & delete cookies."
|
||||||
base_url: "https://postman-echo.com"
|
base_url: "https://postman-echo.com"
|
||||||
verify: False
|
verify: False
|
||||||
export: ["cookie_foo1", "cookie_foo3"]
|
export: ["cookie_foo1"]
|
||||||
|
|
||||||
teststeps:
|
teststeps:
|
||||||
-
|
-
|
||||||
@@ -16,10 +16,11 @@ teststeps:
|
|||||||
headers:
|
headers:
|
||||||
User-Agent: HttpRunner/${get_httprunner_version()}
|
User-Agent: HttpRunner/${get_httprunner_version()}
|
||||||
extract:
|
extract:
|
||||||
cookie_foo1: $.cookies.foo1
|
cookie_foo1: body.cookies.foo1
|
||||||
validate:
|
validate:
|
||||||
- eq: ["status_code", 200]
|
- eq: ["status_code", 200]
|
||||||
- eq: ["cookies.foo1", "bar1"]
|
- eq: ["body.cookies.foo1", "bar1"]
|
||||||
|
- eq: ["body.cookies.foo2", "bar2"]
|
||||||
-
|
-
|
||||||
name: delete cookie foo2
|
name: delete cookie foo2
|
||||||
request:
|
request:
|
||||||
@@ -29,6 +30,5 @@ teststeps:
|
|||||||
User-Agent: HttpRunner/${get_httprunner_version()}
|
User-Agent: HttpRunner/${get_httprunner_version()}
|
||||||
validate:
|
validate:
|
||||||
- eq: ["status_code", 200]
|
- eq: ["status_code", 200]
|
||||||
- ne: ["$.cookies.foo1", "$foo1"]
|
- eq: ["body.cookies.foo1", "bar1"]
|
||||||
- eq: ["$.cookies.foo1", "$cookie_foo1"]
|
- eq: ["body.cookies.foo2", null]
|
||||||
- eq: ["$.cookies.foo3", "$cookie_foo3"]
|
|
||||||
|
|||||||
43
examples/postman_echo/cookie_manipulation/hardcode_test.py
Normal file
43
examples/postman_echo/cookie_manipulation/hardcode_test.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
|
# FROM: cookie_manipulation/hardcode.yml
|
||||||
|
|
||||||
|
|
||||||
|
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestCaseHardcode(HttpRunner):
|
||||||
|
|
||||||
|
config = (
|
||||||
|
Config("set & delete cookies.")
|
||||||
|
.base_url("https://postman-echo.com")
|
||||||
|
.verify(False)
|
||||||
|
.export(*["cookie_foo1"])
|
||||||
|
)
|
||||||
|
|
||||||
|
teststeps = [
|
||||||
|
Step(
|
||||||
|
RunRequest("set cookie foo1 & foo2 & foo3")
|
||||||
|
.get("/cookies/set")
|
||||||
|
.with_params(**{"foo1": "bar1", "foo2": "bar2"})
|
||||||
|
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
|
||||||
|
.extract()
|
||||||
|
.with_jmespath("body.cookies.foo1", "cookie_foo1")
|
||||||
|
.validate()
|
||||||
|
.assert_equal("status_code", 200)
|
||||||
|
.assert_equal("body.cookies.foo1", "bar1")
|
||||||
|
.assert_equal("body.cookies.foo2", "bar2")
|
||||||
|
),
|
||||||
|
Step(
|
||||||
|
RunRequest("delete cookie foo2")
|
||||||
|
.get("/cookies/delete?foo2")
|
||||||
|
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
|
||||||
|
.validate()
|
||||||
|
.assert_equal("status_code", 200)
|
||||||
|
.assert_equal("body.cookies.foo1", "bar1")
|
||||||
|
.assert_equal("body.cookies.foo2", None)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
TestCaseHardcode().test_start()
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
|
# FROM: cookie_manipulation/set_delete_cookies.yml
|
||||||
|
|
||||||
|
|
||||||
|
from httprunner import HttpRunner, Config, Step, RunRequest, RunTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestCaseSetDeleteCookies(HttpRunner):
|
||||||
|
|
||||||
|
config = (
|
||||||
|
Config("set & delete cookies.")
|
||||||
|
.variables(**{"foo1": "bar1", "foo2": "bar2"})
|
||||||
|
.base_url("https://postman-echo.com")
|
||||||
|
.verify(False)
|
||||||
|
.export(*["cookie_foo1", "cookie_foo3"])
|
||||||
|
)
|
||||||
|
|
||||||
|
teststeps = [
|
||||||
|
Step(
|
||||||
|
RunRequest("set cookie foo1 & foo2 & foo3")
|
||||||
|
.with_variables(**{"foo3": "bar3"})
|
||||||
|
.get("/cookies/set")
|
||||||
|
.with_params(**{"foo1": "bar111", "foo2": "$foo2", "foo3": "$foo3"})
|
||||||
|
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
|
||||||
|
.extract()
|
||||||
|
.with_jmespath("$.cookies.foo1", "cookie_foo1")
|
||||||
|
.with_jmespath("$.cookies.foo3", "cookie_foo3")
|
||||||
|
.validate()
|
||||||
|
.assert_equal("status_code", 200)
|
||||||
|
.assert_not_equal("$.cookies.foo3", "$foo3")
|
||||||
|
),
|
||||||
|
Step(
|
||||||
|
RunRequest("delete cookie foo2")
|
||||||
|
.get("/cookies/delete?foo2")
|
||||||
|
.with_headers(**{"User-Agent": "HttpRunner/${get_httprunner_version()}"})
|
||||||
|
.validate()
|
||||||
|
.assert_equal("status_code", 200)
|
||||||
|
.assert_not_equal("$.cookies.foo1", "$foo1")
|
||||||
|
.assert_equal("$.cookies.foo1", "$cookie_foo1")
|
||||||
|
.assert_equal("$.cookies.foo3", "$cookie_foo3")
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
TestCaseSetDeleteCookies().test_start()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/request_with_functions.yml
|
# FROM: request_methods/request_with_functions.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/request_with_testcase_reference.yml
|
# FROM: request_methods/request_with_testcase_reference.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/hardcode.yml
|
# FROM: request_methods/hardcode.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/request_with_functions.yml
|
# FROM: request_methods/request_with_functions.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/request_with_parameters.yml
|
# FROM: request_methods/request_with_parameters.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/request_with_testcase_reference.yml
|
# FROM: request_methods/request_with_testcase_reference.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/request_with_variables.yml
|
# FROM: request_methods/request_with_variables.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/validate_with_functions.yml
|
# FROM: request_methods/validate_with_functions.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# NOTE: Generated By HttpRunner v3.1.4
|
# NOTE: Generated By HttpRunner v3.1.7
|
||||||
# FROM: request_methods/validate_with_variables.yml
|
# FROM: request_methods/validate_with_variables.yml
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = "3.1.6"
|
__version__ = "3.1.8-beta"
|
||||||
__description__ = "One-stop solution for HTTP(S) testing."
|
__description__ = "One-stop solution for HTTP(S) testing."
|
||||||
|
|
||||||
# import firstly for monkey patch if needed
|
# import firstly for monkey patch if needed
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from sentry_sdk import capture_message
|
|
||||||
|
|
||||||
from httprunner import __description__, __version__
|
from httprunner import __description__, __version__
|
||||||
from httprunner.compat import ensure_cli_args
|
from httprunner.compat import ensure_cli_args
|
||||||
from httprunner.ext.har2case import init_har2case_parser, main_har2case
|
from httprunner.ext.har2case import init_har2case_parser, main_har2case
|
||||||
from httprunner.make import init_make_parser, main_make
|
from httprunner.make import init_make_parser, main_make
|
||||||
from httprunner.scaffold import init_parser_scaffold, main_scaffold
|
from httprunner.scaffold import init_parser_scaffold, main_scaffold
|
||||||
from httprunner.utils import init_sentry_sdk
|
from httprunner.utils import init_sentry_sdk, ga_client
|
||||||
|
|
||||||
init_sentry_sdk()
|
init_sentry_sdk()
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ def init_parser_run(subparsers):
|
|||||||
|
|
||||||
|
|
||||||
def main_run(extra_args) -> enum.IntEnum:
|
def main_run(extra_args) -> enum.IntEnum:
|
||||||
capture_message("start to run")
|
ga_client.track_event("RunAPITests", "hrun")
|
||||||
# keep compatibility with v2
|
# keep compatibility with v2
|
||||||
extra_args = ensure_cli_args(extra_args)
|
extra_args = ensure_cli_args(extra_args)
|
||||||
|
|
||||||
|
|||||||
@@ -181,19 +181,19 @@ class HttpSession(requests.Session):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
client_ip, client_port = response.raw.connection.sock.getsockname()
|
client_ip, client_port = response.raw.connection.sock.getsockname()
|
||||||
self.data.address.client_ip = client_ip
|
except AttributeError:
|
||||||
self.data.address.client_port = client_port
|
client_ip, client_port = response.raw.connection.sock.socket.getsockname()
|
||||||
logger.debug(f"client IP: {client_ip}, Port: {client_port}")
|
self.data.address.client_ip = client_ip
|
||||||
except AttributeError as ex:
|
self.data.address.client_port = client_port
|
||||||
logger.warning(f"failed to get client address info: {ex}")
|
logger.debug(f"client IP: {client_ip}, Port: {client_port}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
server_ip, server_port = response.raw.connection.sock.getpeername()
|
server_ip, server_port = response.raw.connection.sock.getpeername()
|
||||||
self.data.address.server_ip = server_ip
|
except AttributeError:
|
||||||
self.data.address.server_port = server_port
|
server_ip, server_port = response.raw.connection.sock.socket.getpeername()
|
||||||
logger.debug(f"server IP: {server_ip}, Port: {server_port}")
|
self.data.address.server_ip = server_ip
|
||||||
except AttributeError as ex:
|
self.data.address.server_port = server_port
|
||||||
logger.warning(f"failed to get server address info: {ex}")
|
logger.debug(f"server IP: {server_ip}, Port: {server_port}")
|
||||||
|
|
||||||
# get length of the response content
|
# get length of the response content
|
||||||
content_size = int(dict(response.headers).get("content-length") or 0)
|
content_size = int(dict(response.headers).get("content-length") or 0)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Usage:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from httprunner.ext.har2case.core import HarParser
|
from httprunner.ext.har2case.core import HarParser
|
||||||
from sentry_sdk import capture_message
|
from httprunner.utils import ga_client
|
||||||
|
|
||||||
|
|
||||||
def init_har2case_parser(subparsers):
|
def init_har2case_parser(subparsers):
|
||||||
@@ -64,7 +64,7 @@ def main_har2case(args):
|
|||||||
else:
|
else:
|
||||||
output_file_type = "pytest"
|
output_file_type = "pytest"
|
||||||
|
|
||||||
capture_message(f"har2case {output_file_type}")
|
ga_client.track_event("ConvertTests", f"har2case {output_file_type}")
|
||||||
HarParser(har_source_file, args.filter, args.exclude, args.profile).gen_testcase(output_file_type)
|
HarParser(har_source_file, args.filter, args.exclude, args.profile).gen_testcase(output_file_type)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -70,11 +70,8 @@ def prepare_locust_tests() -> List:
|
|||||||
def main_locusts():
|
def main_locusts():
|
||||||
""" locusts entrance
|
""" locusts entrance
|
||||||
"""
|
"""
|
||||||
from httprunner.utils import init_sentry_sdk
|
from httprunner.utils import ga_client
|
||||||
from sentry_sdk import capture_message
|
ga_client.track_event("RunLoadTests", "locust")
|
||||||
|
|
||||||
init_sentry_sdk()
|
|
||||||
capture_message("start to run locusts")
|
|
||||||
|
|
||||||
# avoid print too much log details in console
|
# avoid print too much log details in console
|
||||||
logger.remove()
|
logger.remove()
|
||||||
|
|||||||
@@ -4,23 +4,14 @@ import json
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
from typing import Tuple, Dict, Union, Text, List, Callable
|
from typing import Callable, Dict, List, Text, Tuple, Union
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
|
|
||||||
from httprunner import builtin, utils
|
from httprunner import builtin, exceptions, utils
|
||||||
from httprunner import exceptions
|
from httprunner.models import ProjectMeta, TestCase, TestSuite
|
||||||
from httprunner.models import TestCase, ProjectMeta, TestSuite
|
|
||||||
|
|
||||||
try:
|
|
||||||
# PyYAML version >= 5.1
|
|
||||||
# ref: https://github.com/yaml/pyyaml/wiki/PyYAML-yaml.load(input)-Deprecation
|
|
||||||
yaml.warnings({"YAMLLoadWarning": False})
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
project_meta: Union[ProjectMeta, None] = None
|
project_meta: Union[ProjectMeta, None] = None
|
||||||
|
|
||||||
@@ -30,7 +21,7 @@ def _load_yaml_file(yaml_file: Text) -> Dict:
|
|||||||
"""
|
"""
|
||||||
with open(yaml_file, mode="rb") as stream:
|
with open(yaml_file, mode="rb") as stream:
|
||||||
try:
|
try:
|
||||||
yaml_content = yaml.load(stream)
|
yaml_content = yaml.load(stream, Loader=yaml.FullLoader)
|
||||||
except yaml.YAMLError as ex:
|
except yaml.YAMLError as ex:
|
||||||
err_msg = f"YAMLError:\nfile: {yaml_file}\nerror: {ex}"
|
err_msg = f"YAMLError:\nfile: {yaml_file}\nerror: {ex}"
|
||||||
logger.error(err_msg)
|
logger.error(err_msg)
|
||||||
@@ -130,6 +121,9 @@ def load_dot_env_file(dot_env_path: Text) -> Dict:
|
|||||||
with open(dot_env_path, mode="rb") as fp:
|
with open(dot_env_path, mode="rb") as fp:
|
||||||
for line in fp:
|
for line in fp:
|
||||||
# maxsplit=1
|
# maxsplit=1
|
||||||
|
line = line.strip()
|
||||||
|
if not len(line) or line.startswith(b"#"):
|
||||||
|
continue
|
||||||
if b"=" in line:
|
if b"=" in line:
|
||||||
variable, value = line.split(b"=", 1)
|
variable, value = line.split(b"=", 1)
|
||||||
elif b":" in line:
|
elif b":" in line:
|
||||||
@@ -450,4 +444,4 @@ def convert_relative_project_root_dir(abs_path: Text) -> Text:
|
|||||||
f"project_meta.RootDir: {_project_meta.RootDir}"
|
f"project_meta.RootDir: {_project_meta.RootDir}"
|
||||||
)
|
)
|
||||||
|
|
||||||
return abs_path[len(_project_meta.RootDir) + 1 :]
|
return abs_path[len(_project_meta.RootDir) + 1:]
|
||||||
|
|||||||
@@ -2,29 +2,21 @@ import os
|
|||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from typing import Text, List, Tuple, Dict, Set, NoReturn
|
from typing import Dict, List, NoReturn, Set, Text, Tuple
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from sentry_sdk import capture_exception
|
from sentry_sdk import capture_exception
|
||||||
|
|
||||||
from httprunner import exceptions, __version__
|
from httprunner import __version__, exceptions
|
||||||
from httprunner.compat import (
|
from httprunner.compat import (convert_variables, ensure_path_sep,
|
||||||
ensure_testcase_v3_api,
|
ensure_testcase_v3, ensure_testcase_v3_api)
|
||||||
ensure_testcase_v3,
|
from httprunner.loader import (convert_relative_project_root_dir,
|
||||||
convert_variables,
|
load_folder_files, load_project_meta,
|
||||||
ensure_path_sep,
|
load_test_file, load_testcase, load_testsuite)
|
||||||
)
|
|
||||||
from httprunner.loader import (
|
|
||||||
load_folder_files,
|
|
||||||
load_test_file,
|
|
||||||
load_testcase,
|
|
||||||
load_testsuite,
|
|
||||||
load_project_meta,
|
|
||||||
convert_relative_project_root_dir,
|
|
||||||
)
|
|
||||||
from httprunner.response import uniform_validator
|
from httprunner.response import uniform_validator
|
||||||
from httprunner.utils import merge_variables, is_support_multiprocessing
|
from httprunner.utils import (ga_client, is_support_multiprocessing,
|
||||||
|
merge_variables)
|
||||||
|
|
||||||
""" cache converted pytest files, avoid duplicate making
|
""" cache converted pytest files, avoid duplicate making
|
||||||
"""
|
"""
|
||||||
@@ -80,10 +72,10 @@ if __name__ == "__main__":
|
|||||||
def __ensure_absolute(path: Text) -> Text:
|
def __ensure_absolute(path: Text) -> Text:
|
||||||
if path.startswith("./"):
|
if path.startswith("./"):
|
||||||
# Linux/Darwin, hrun ./test.yml
|
# Linux/Darwin, hrun ./test.yml
|
||||||
path = path[len("./") :]
|
path = path[len("./"):]
|
||||||
elif path.startswith(".\\"):
|
elif path.startswith(".\\"):
|
||||||
# Windows, hrun .\\test.yml
|
# Windows, hrun .\\test.yml
|
||||||
path = path[len(".\\") :]
|
path = path[len(".\\"):]
|
||||||
|
|
||||||
path = ensure_path_sep(path)
|
path = ensure_path_sep(path)
|
||||||
project_meta = load_project_meta(path)
|
project_meta = load_project_meta(path)
|
||||||
@@ -173,7 +165,7 @@ def format_pytest_with_black(*python_paths: Text) -> NoReturn:
|
|||||||
subprocess.run(["black", *python_paths])
|
subprocess.run(["black", *python_paths])
|
||||||
else:
|
else:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"this system does not support multiprocessing well, format files one by one ..."
|
"this system does not support multiprocessing well, format files one by one ..."
|
||||||
)
|
)
|
||||||
[subprocess.run(["black", path]) for path in python_paths]
|
[subprocess.run(["black", path]) for path in python_paths]
|
||||||
except subprocess.CalledProcessError as ex:
|
except subprocess.CalledProcessError as ex:
|
||||||
@@ -590,6 +582,8 @@ def main_make(tests_paths: List[Text]) -> List[Text]:
|
|||||||
if not tests_paths:
|
if not tests_paths:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
ga_client.track_event("ConvertTests", "hmake")
|
||||||
|
|
||||||
for tests_path in tests_paths:
|
for tests_path in tests_paths:
|
||||||
tests_path = ensure_path_sep(tests_path)
|
tests_path = ensure_path_sep(tests_path)
|
||||||
if not os.path.isabs(tests_path):
|
if not os.path.isabs(tests_path):
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from sentry_sdk import capture_message
|
|
||||||
|
from httprunner.utils import ga_client
|
||||||
|
|
||||||
|
|
||||||
def init_parser_scaffold(subparsers):
|
def init_parser_scaffold(subparsers):
|
||||||
@@ -199,5 +200,5 @@ def sleep(n_secs):
|
|||||||
|
|
||||||
|
|
||||||
def main_scaffold(args):
|
def main_scaffold(args):
|
||||||
capture_message("startproject with scaffold")
|
ga_client.track_event("Scaffold", "startproject")
|
||||||
sys.exit(create_scaffold(args.project_name))
|
sys.exit(create_scaffold(args.project_name))
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
|
import itertools
|
||||||
import json
|
import json
|
||||||
import os.path
|
import os.path
|
||||||
import platform
|
import platform
|
||||||
import uuid
|
import uuid
|
||||||
from multiprocessing import Queue
|
from multiprocessing import Queue
|
||||||
import itertools
|
from typing import Any, Dict, List, Text
|
||||||
from typing import Dict, List, Any, Union, Text
|
|
||||||
|
|
||||||
|
import requests
|
||||||
import sentry_sdk
|
import sentry_sdk
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from httprunner import __version__
|
from httprunner import __version__, exceptions
|
||||||
from httprunner import exceptions
|
|
||||||
from httprunner.models import VariablesMapping
|
from httprunner.models import VariablesMapping
|
||||||
|
|
||||||
|
|
||||||
@@ -25,6 +25,48 @@ def init_sentry_sdk():
|
|||||||
scope.set_user({"id": uuid.getnode()})
|
scope.set_user({"id": uuid.getnode()})
|
||||||
|
|
||||||
|
|
||||||
|
class GAClient(object):
|
||||||
|
|
||||||
|
version = '1' # GA API Version
|
||||||
|
report_url = 'https://www.google-analytics.com/collect'
|
||||||
|
report_debug_url = 'https://www.google-analytics.com/debug/collect' # used for debug
|
||||||
|
|
||||||
|
def __init__(self, tracking_id: Text):
|
||||||
|
self.http_client = requests.Session()
|
||||||
|
self.label = str(__version__)
|
||||||
|
self.common_params = {
|
||||||
|
'v': self.version,
|
||||||
|
'tid': tracking_id, # Tracking ID / Property ID, XX-XXXXXXX-X
|
||||||
|
'cid': uuid.getnode(), # Anonymous Client ID
|
||||||
|
'ua': f'HttpRunner/{__version__}',
|
||||||
|
}
|
||||||
|
|
||||||
|
def track_event(self, category: Text, action: Text, value: int = 0):
|
||||||
|
data = {
|
||||||
|
't': 'event', # Event hit type = event
|
||||||
|
'ec': category, # Required. Event Category.
|
||||||
|
'ea': action, # Required. Event Action.
|
||||||
|
'el': self.label, # Optional. Event label, used as version.
|
||||||
|
'ev': value, # Optional. Event value, must be non-negative integer
|
||||||
|
}
|
||||||
|
data.update(self.common_params)
|
||||||
|
self.http_client.post(self.report_url, data=data)
|
||||||
|
|
||||||
|
def track_user_timing(self, category: Text, variable: Text, duration: int):
|
||||||
|
data = {
|
||||||
|
't': 'timing', # Event hit type = timing
|
||||||
|
'utc': category, # Required. user timing category. e.g. jsonLoader
|
||||||
|
'utv': variable, # Required. timing variable. e.g. load
|
||||||
|
'utt': duration, # Required. time took duration.
|
||||||
|
'utl': self.label, # Optional. user timing label, used as version.
|
||||||
|
}
|
||||||
|
data.update(self.common_params)
|
||||||
|
self.http_client.post(self.report_url, data=data)
|
||||||
|
|
||||||
|
|
||||||
|
ga_client = GAClient("UA-114587036-1")
|
||||||
|
|
||||||
|
|
||||||
def set_os_environ(variables_mapping):
|
def set_os_environ(variables_mapping):
|
||||||
""" set variables mapping to os.environ
|
""" set variables mapping to os.environ
|
||||||
"""
|
"""
|
||||||
|
|||||||
24
mkdocs.yml
24
mkdocs.yml
@@ -1,6 +1,9 @@
|
|||||||
# install mkdocs
|
# install mkdocs and material design
|
||||||
# $ pip install mkdocs # 1.1.2
|
# $ pip install mkdocs-material
|
||||||
# $ pip install mkdocs-material # 5.2.2
|
|
||||||
|
# usage
|
||||||
|
# $ mkdocs serve # build docs and preview
|
||||||
|
# $ mkdocs gh-deploy # Deploy your documentation to GitHub Pages
|
||||||
|
|
||||||
# Project information
|
# Project information
|
||||||
site_name: HttpRunner V3.x Docs
|
site_name: HttpRunner V3.x Docs
|
||||||
@@ -13,7 +16,7 @@ repo_url: https://github.com/httprunner/httprunner
|
|||||||
edit_uri: ""
|
edit_uri: ""
|
||||||
|
|
||||||
# Copyright
|
# Copyright
|
||||||
copyright: 'Copyright © 2017 - 2020 debugtalk'
|
copyright: 'Copyright © 2017 - 2021 debugtalk'
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
theme:
|
theme:
|
||||||
@@ -26,11 +29,6 @@ theme:
|
|||||||
text: 'Roboto'
|
text: 'Roboto'
|
||||||
code: 'Roboto Mono'
|
code: 'Roboto Mono'
|
||||||
|
|
||||||
# Google Analytics
|
|
||||||
google_analytics:
|
|
||||||
- 'UA-114587036-3'
|
|
||||||
- 'auto'
|
|
||||||
|
|
||||||
# Extensions
|
# Extensions
|
||||||
markdown_extensions:
|
markdown_extensions:
|
||||||
- admonition
|
- admonition
|
||||||
@@ -38,6 +36,9 @@ markdown_extensions:
|
|||||||
guess_lang: false
|
guess_lang: false
|
||||||
- toc:
|
- toc:
|
||||||
permalink: true
|
permalink: true
|
||||||
|
- def_list
|
||||||
|
- pymdownx.tasklist:
|
||||||
|
custom_checkbox: true
|
||||||
|
|
||||||
# extra
|
# extra
|
||||||
extra:
|
extra:
|
||||||
@@ -48,10 +49,13 @@ extra:
|
|||||||
link: https://debugtalk.com
|
link: https://debugtalk.com
|
||||||
- icon: fontawesome/brands/github-alt
|
- icon: fontawesome/brands/github-alt
|
||||||
link: 'https://github.com/httprunner'
|
link: 'https://github.com/httprunner'
|
||||||
|
analytics:
|
||||||
|
provider: google # Google Analytics
|
||||||
|
property: UA-114587036-3
|
||||||
|
|
||||||
# index pages
|
# index pages
|
||||||
nav:
|
nav:
|
||||||
- Introduction: index.md
|
- README: README.md
|
||||||
- Installation: installation.md
|
- Installation: installation.md
|
||||||
- User Guide:
|
- User Guide:
|
||||||
- Concepts: user/concepts.md
|
- Concepts: user/concepts.md
|
||||||
|
|||||||
1869
poetry.lock
generated
1869
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "httprunner"
|
name = "httprunner"
|
||||||
version = "3.1.6"
|
version = "3.1.8-beta"
|
||||||
description = "One-stop solution for HTTP(S) testing."
|
description = "One-stop solution for HTTP(S) testing."
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "docs/README.md"
|
||||||
authors = ["debugtalk <debugtalk@gmail.com>"]
|
authors = ["debugtalk <debugtalk@gmail.com>"]
|
||||||
|
|
||||||
homepage = "https://github.com/httprunner/httprunner"
|
homepage = "https://github.com/httprunner/httprunner"
|
||||||
@@ -20,30 +20,31 @@ classifiers = [
|
|||||||
"Operating System :: MacOS",
|
"Operating System :: MacOS",
|
||||||
"Operating System :: POSIX :: Linux",
|
"Operating System :: POSIX :: Linux",
|
||||||
"Operating System :: Microsoft :: Windows",
|
"Operating System :: Microsoft :: Windows",
|
||||||
"Programming Language :: Python :: 3.6",
|
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
"Programming Language :: Python :: 3.8"
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: 3.9",
|
||||||
|
"Programming Language :: Python :: 3.10"
|
||||||
]
|
]
|
||||||
|
|
||||||
include = ["docs/CHANGELOG.md"]
|
include = ["docs/CHANGELOG.md"]
|
||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.6"
|
python = "^3.7"
|
||||||
requests = "^2.22.0"
|
requests = "^2.22.0"
|
||||||
pyyaml = "^5.1.2"
|
pyyaml = "^5.4.1"
|
||||||
jinja2 = "^2.10.3"
|
pydantic = "~1.8" # >=1.8.0 <1.9.0
|
||||||
pydantic = "^1.4"
|
|
||||||
loguru = "^0.4.1"
|
loguru = "^0.4.1"
|
||||||
jmespath = "^0.9.5"
|
jmespath = "^0.9.5"
|
||||||
black = "^19.10b0"
|
black = "^19.10b0"
|
||||||
pytest = "^5.4.2"
|
pytest = "^7.1.1"
|
||||||
pytest-html = "^2.1.1"
|
pytest-html = "^3.1.1"
|
||||||
sentry-sdk = "^0.14.4"
|
sentry-sdk = "^0.14.4"
|
||||||
allure-pytest = {version = "^2.8.16", optional = true}
|
allure-pytest = {version = "^2.8.16", optional = true}
|
||||||
requests-toolbelt = {version = "^0.9.1", optional = true}
|
requests-toolbelt = {version = "^0.9.1", optional = true}
|
||||||
filetype = {version = "^1.0.7", optional = true}
|
filetype = {version = "^1.0.7", optional = true}
|
||||||
locust = {version = "^1.0.3", optional = true}
|
locust = {version = "^1.0.3", optional = true}
|
||||||
Brotli = "^1.0.9"
|
Brotli = "^1.0.9"
|
||||||
|
jinja2 = "^3.0.3"
|
||||||
|
|
||||||
[tool.poetry.extras]
|
[tool.poetry.extras]
|
||||||
allure = ["allure-pytest"] # pip install "httprunner[allure]", poetry install -E allure
|
allure = ["allure-pytest"] # pip install "httprunner[allure]", poetry install -E allure
|
||||||
@@ -52,8 +53,8 @@ locust = ["locust"] # pip install "httprunner[locust]",
|
|||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
coverage = "^4.5.4"
|
coverage = "^4.5.4"
|
||||||
uvicorn = "^0.11.3"
|
fastapi = "^0.70.0"
|
||||||
fastapi = "^0.49.0"
|
uvicorn = "^0.17.6"
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
httprunner = "httprunner.cli:main"
|
httprunner = "httprunner.cli:main"
|
||||||
@@ -65,3 +66,7 @@ locusts = "httprunner.ext.locust:main_locusts"
|
|||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry>=1.0.0"]
|
requires = ["poetry>=1.0.0"]
|
||||||
build-backend = "poetry.masonry.api"
|
build-backend = "poetry.masonry.api"
|
||||||
|
|
||||||
|
[[tool.poetry.source]]
|
||||||
|
name = "tsinghua"
|
||||||
|
url = "https://pypi.tuna.tsinghua.edu.cn/simple/"
|
||||||
|
|||||||
@@ -107,8 +107,8 @@ from request_methods.request_with_functions_test import (
|
|||||||
)
|
)
|
||||||
loader.project_meta = None
|
loader.project_meta = None
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
ensure_file_abs_path_valid(os.path.join(os.getcwd(), "README.md")),
|
ensure_file_abs_path_valid(os.path.join(os.getcwd(), "pyproject.toml")),
|
||||||
os.path.join(os.getcwd(), "README.md"),
|
os.path.join(os.getcwd(), "pyproject.toml"),
|
||||||
)
|
)
|
||||||
loader.project_meta = None
|
loader.project_meta = None
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class TestScaffold(unittest.TestCase):
|
|||||||
|
|
||||||
# run demo testcases
|
# run demo testcases
|
||||||
try:
|
try:
|
||||||
if platform.system() is "Windows":
|
if platform.system() == "Windows":
|
||||||
subprocess.check_call(["hrun", project_name], shell=True)
|
subprocess.check_call(["hrun", project_name], shell=True)
|
||||||
else:
|
else:
|
||||||
subprocess.check_call(["hrun", project_name])
|
subprocess.check_call(["hrun", project_name])
|
||||||
|
|||||||
Reference in New Issue
Block a user