mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
update docs with mkdocs
This commit is contained in:
19
docs/FAQ.rst
19
docs/FAQ.rst
@@ -1,19 +0,0 @@
|
||||
FAQ
|
||||
===
|
||||
|
||||
Unable to install PyUnitReport dependency library automatically
|
||||
---------------------------------------------------------------
|
||||
|
||||
If there is something goes wrong in installation like below. ::
|
||||
|
||||
Downloading/unpacking PyUnitReport (from HttpRunner)
|
||||
Could not find any downloads that satisfy the requirement PyUnitReport (from HttpRunner)
|
||||
|
||||
You could install ``PyUnitReport`` manully at first. ::
|
||||
|
||||
pip install PyUnitReport
|
||||
|
||||
|
||||
And then everything will be OK when you reinstall ``HttpRunner``. ::
|
||||
|
||||
pip install HttpRunner
|
||||
78
docs/Installation.md
Normal file
78
docs/Installation.md
Normal file
@@ -0,0 +1,78 @@
|
||||
## Installation
|
||||
|
||||
`HttpRunner` is available on [`PyPI`][PyPI] and can be installed through pip or easy_install.
|
||||
|
||||
```bash
|
||||
$ pip install HttpRunner
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```bash
|
||||
$ easy_install HttpRunner
|
||||
```
|
||||
|
||||
If you want to keep up with the latest version, you can install with github repository url.
|
||||
|
||||
```bash
|
||||
$ pip install git+https://github.com/HttpRunner/HttpRunner.git#egg=HttpRunner
|
||||
```
|
||||
|
||||
## Upgrade
|
||||
|
||||
If you have installed `HttpRunner` before and want to upgrade to the latest version, you can use the `-U` option.
|
||||
|
||||
This option works on each installation method described above.
|
||||
|
||||
```bash
|
||||
$ pip install -U HttpRunner
|
||||
$ easy_install -U HttpRunner
|
||||
$ pip install -U git+https://github.com/HttpRunner/HttpRunner.git#egg=HttpRunner
|
||||
```
|
||||
|
||||
## Check Installation
|
||||
|
||||
When HttpRunner is installed, a **httprunner** (**hrun** for short) command should be available in your shell (if you're not using
|
||||
virtualenv—which you should—make sure your python script directory is on your path).
|
||||
|
||||
To see `HttpRunner` version:
|
||||
|
||||
```bash
|
||||
$ httprunner -V # same as: hrun -V
|
||||
HttpRunner version: 0.8.1b
|
||||
PyUnitReport version: 0.1.3b
|
||||
```
|
||||
|
||||
To see available options, run:
|
||||
|
||||
```bash
|
||||
$ httprunner -h # same as: hrun -h
|
||||
usage: httprunner [-h] [-V] [--log-level LOG_LEVEL] [--report-name REPORT_NAME]
|
||||
[--failfast] [--startproject STARTPROJECT]
|
||||
[testset_paths [testset_paths ...]]
|
||||
|
||||
HttpRunner.
|
||||
|
||||
positional arguments:
|
||||
testset_paths testset file path
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-V, --version show version
|
||||
--log-level LOG_LEVEL
|
||||
Specify logging level, default is INFO.
|
||||
--report-name REPORT_NAME
|
||||
Specify report name, default is generated time.
|
||||
--failfast Stop the test run on the first error or failure.
|
||||
--startproject STARTPROJECT
|
||||
Specify new project name.
|
||||
```
|
||||
|
||||
## Supported Python Versions
|
||||
|
||||
HttpRunner supports Python 2.7, 3.4, 3.5, and 3.6. And we strongly recommend you to use `Python 3.6`.
|
||||
|
||||
`HttpRunner` has been tested on `macOS`, `Linux` and `Windows` platforms.
|
||||
|
||||
|
||||
[PyPI]: https://pypi.python.org/pypi
|
||||
@@ -1,76 +0,0 @@
|
||||
.. default-role:: code
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
``HttpRunner`` is available on `PyPI`_ and can be installed through pip or easy_install. ::
|
||||
|
||||
$ pip install HttpRunner
|
||||
|
||||
or ::
|
||||
|
||||
$ easy_install HttpRunner
|
||||
|
||||
|
||||
If you want to keep up with the latest version, you can install with github repository url. ::
|
||||
|
||||
$ pip install git+https://github.com/HttpRunner/HttpRunner.git#egg=HttpRunner
|
||||
|
||||
|
||||
Upgrade
|
||||
-------
|
||||
|
||||
If you have installed ``HttpRunner`` before and want to upgrade to the latest version, you can use the ``-U`` option.
|
||||
|
||||
This option works on each installation method described above. ::
|
||||
|
||||
$ pip install -U HttpRunner
|
||||
$ easy_install -U HttpRunner
|
||||
$ pip install -U git+https://github.com/HttpRunner/HttpRunner.git#egg=HttpRunner
|
||||
|
||||
|
||||
Check Installation
|
||||
------------------
|
||||
|
||||
When HttpRunner is installed, a **httprunner** (**hrun** for short) command should be available in your shell (if you're not using
|
||||
virtualenv—which you should—make sure your python script directory is on your path).
|
||||
|
||||
To see ``HttpRunner`` version: ::
|
||||
|
||||
$ httprunner -V # same as: hrun -V
|
||||
HttpRunner version: 0.8.1b
|
||||
PyUnitReport version: 0.1.3b
|
||||
|
||||
To see available options, run::
|
||||
|
||||
$ httprunner -h # same as: hrun -h
|
||||
usage: httprunner [-h] [-V] [--log-level LOG_LEVEL] [--report-name REPORT_NAME]
|
||||
[--failfast] [--startproject STARTPROJECT]
|
||||
[testset_paths [testset_paths ...]]
|
||||
|
||||
HttpRunner.
|
||||
|
||||
positional arguments:
|
||||
testset_paths testset file path
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-V, --version show version
|
||||
--log-level LOG_LEVEL
|
||||
Specify logging level, default is INFO.
|
||||
--report-name REPORT_NAME
|
||||
Specify report name, default is generated time.
|
||||
--failfast Stop the test run on the first error or failure.
|
||||
--startproject STARTPROJECT
|
||||
Specify new project name.
|
||||
|
||||
|
||||
Supported Python Versions
|
||||
-------------------------
|
||||
|
||||
HttpRunner supports Python 2.7, 3.4, 3.5, and 3.6. And we strongly recommend you to use ``Python 3.6``.
|
||||
|
||||
``HttpRunner`` has been tested on ``macOS``, ``Linux`` and ``Windows`` platforms.
|
||||
|
||||
|
||||
.. _PyPI: https://pypi.python.org/pypi
|
||||
@@ -1,20 +0,0 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = python -msphinx
|
||||
SPHINXPROJ = HttpRunner
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
15
docs/_static/my.css
vendored
15
docs/_static/my.css
vendored
@@ -1,15 +0,0 @@
|
||||
@import 'https://media.readthedocs.org/css/sphinx_rtd_theme.css';
|
||||
|
||||
.wy-nav-content {
|
||||
max-width: 1020px
|
||||
}
|
||||
|
||||
.rst-content .topic {
|
||||
border: silver 1px solid;
|
||||
margin: 10px auto;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.rst-content .highlight>pre {
|
||||
line-height: 1.5;
|
||||
}
|
||||
192
docs/conf.py
192
docs/conf.py
@@ -1,192 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# HttpRunner documentation build configuration file, created by
|
||||
# sphinx-quickstart on Wed Nov 8 14:28:04 2017.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
import os
|
||||
on_rtd = os.environ.get('READTHEDOCS') == 'True'
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#
|
||||
# needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.githubpages'
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix(es) of source filenames.
|
||||
# You can specify multiple suffix as a list of string:
|
||||
#
|
||||
from recommonmark.parser import CommonMarkParser
|
||||
|
||||
source_parsers = {
|
||||
'.md': CommonMarkParser,
|
||||
}
|
||||
source_suffix = ['.rst', '.md']
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'HttpRunner'
|
||||
copyright = '2017, DebugTalk'
|
||||
author = 'debugtalk'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.8.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = 'zh'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
if on_rtd:
|
||||
html_theme = 'default'
|
||||
html_context = {
|
||||
'css_files': [
|
||||
'https://media.readthedocs.org/css/sphinx_rtd_theme.css',
|
||||
'https://media.readthedocs.org/css/readthedocs-doc-embed.css',
|
||||
'_static/my.css',
|
||||
],
|
||||
}
|
||||
else:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
html_style = 'my.css'
|
||||
|
||||
html_show_sourcelink = False
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#
|
||||
# html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# Custom sidebar templates, must be a dictionary that maps document names
|
||||
# to template names.
|
||||
#
|
||||
# This is required for the alabaster theme
|
||||
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
|
||||
# html_sidebars = {
|
||||
# '**': [
|
||||
# 'about.html',
|
||||
# 'navigation.html',
|
||||
# 'relations.html', # needs 'show_related': True theme option to display
|
||||
# 'searchbox.html',
|
||||
# # 'donate.html',
|
||||
# ]
|
||||
# }
|
||||
|
||||
|
||||
# -- Options for HTMLHelp output ------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'HttpRunnerdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'HttpRunner.tex', 'HttpRunner Documentation',
|
||||
'debugtalk', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'httprunner', 'HttpRunner Documentation',
|
||||
[author], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'HttpRunner', 'HttpRunner Documentation',
|
||||
author, 'HttpRunner', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
3
docs/index.md
Normal file
3
docs/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Welcome to HttpRunner's documentation!
|
||||
|
||||
点击此处查看[中文使用说明文档](http://cn.httprunner.top)。
|
||||
@@ -1,20 +0,0 @@
|
||||
.. HttpRunner documentation master file, created by
|
||||
sphinx-quickstart on Wed Nov 8 14:28:04 2017.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to HttpRunner's documentation!
|
||||
======================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:caption: Contents
|
||||
|
||||
Introduction
|
||||
Installation
|
||||
quickstart
|
||||
write-testcases
|
||||
run-testcases
|
||||
load-test
|
||||
development
|
||||
FAQ
|
||||
@@ -328,8 +328,8 @@ This is just a starting point, see the `advanced guide` for the advanced feature
|
||||
|
||||
[requests]: http://docs.python-requests.org/en/master/
|
||||
[requests.request]: http://docs.python-requests.org/en/master/api/#requests.request
|
||||
[comparator]: comparator.md
|
||||
[extraction-and-validation]: extraction-and-validation.md
|
||||
[comparator]: write-testcases.md#comparator
|
||||
[extraction-and-validation]: write-testcases.md#extraction-and-validation
|
||||
[quickstart-demo-rev-0]: ../examples/quickstart-demo-rev-0.yml
|
||||
[quickstart-demo-rev-1]: ../examples/quickstart-demo-rev-1.yml
|
||||
[quickstart-demo-rev-2]: ../examples/quickstart-demo-rev-2.yml
|
||||
|
||||
142
docs/write-testcases.md
Normal file
142
docs/write-testcases.md
Normal file
@@ -0,0 +1,142 @@
|
||||
It is recommended to write testcases in `YAML` format.
|
||||
|
||||
## demo
|
||||
|
||||
Here is a testset example of typical scenario: get `token` at the beginning, and each subsequent requests should take the `token` in the headers.
|
||||
|
||||
```yaml
|
||||
- config:
|
||||
name: "create user testsets."
|
||||
variables:
|
||||
- user_agent: 'iOS/10.3'
|
||||
- device_sn: ${gen_random_string(15)}
|
||||
- os_platform: 'ios'
|
||||
- app_version: '2.8.6'
|
||||
request:
|
||||
base_url: "http://127.0.0.1:5000"
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: $device_sn
|
||||
|
||||
- test:
|
||||
name: get token
|
||||
request:
|
||||
url: /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:
|
||||
- eq: ["status_code", 200]
|
||||
- len_eq: ["content.token", 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:
|
||||
- eq: ["status_code", 201]
|
||||
- eq: ["content.success", true]
|
||||
```
|
||||
|
||||
Function invoke is supported in `YAML/JSON` format testcases, such as `gen_random_string` and `get_sign` above. This mechanism relies on the `debugtak.py` hot plugin, with which we can define functions in `debugtak.py` file, and then functions can be auto discovered and invoked in runtime.
|
||||
|
||||
For detailed regulations of writing testcases, you can read the [`quickstart`](quickstart.md) documents.
|
||||
|
||||
|
||||
## Comparator
|
||||
|
||||
`HttpRunner` currently supports the following comparators.
|
||||
|
||||
| comparator | Description | A(check), B(expect) | examples |
|
||||
| -- | -- | -- | -- |
|
||||
| `eq`, `==` | value is equal | A == B | 9 eq 9 |
|
||||
| `lt` | less than | A < B | 7 lt 8 |
|
||||
| `le` | less than or equals | A <= B | 7 le 8, 8 le 8 |
|
||||
| `gt` | greater than | A > B | 8 gt 7 |
|
||||
| `ge` | greater than or equals | A >= B | 8 ge 7, 8 ge 8 |
|
||||
| `ne` | not equals | A != B | 6 ne 9 |
|
||||
| `str_eq` | string equals | str(A) == str(B) | 123 str_eq '123' |
|
||||
| `len_eq`, `count_eq` | length or count equals | len(A) == B | 'abc' len_eq 3, [1,2] len_eq 2 |
|
||||
| `len_gt`, `count_gt` | length greater than | len(A) > B | 'abc' len_gt 2, [1,2,3] len_gt 2 |
|
||||
| `len_ge`, `count_ge` | length greater than or equals | len(A) >= B | 'abc' len_ge 3, [1,2,3] len_gt 3 |
|
||||
| `len_lt`, `count_lt` | length less than | len(A) < B | 'abc' len_lt 4, [1,2,3] len_lt 4 |
|
||||
| `len_le`, `count_le` | length less than or equals | len(A) <= B | 'abc' len_le 3, [1,2,3] len_le 3 |
|
||||
| `contains` | contains | [1, 2] contains 1 | 'abc' contains 'a', [1,2,3] len_lt 4 |
|
||||
| `contained_by` | contained by | A in B | 'a' contained_by 'abc', 1 contained_by [1,2] |
|
||||
| `type_match` | A is instance of B | isinstance(A, B) | 123 type_match 'int' |
|
||||
| `regex_match` | regex matches | re.match(B, A) | 'abcdef' regex 'a\w+d' |
|
||||
| `startswith` | starts with | A.startswith(B) is True | 'abc' startswith 'ab' |
|
||||
| `endswith` | ends with | A.endswith(B) is True | 'abc' endswith 'bc' |
|
||||
|
||||
|
||||
## Extraction and Validation
|
||||
|
||||
Suppose we get the following HTTP response.
|
||||
|
||||
```javascript
|
||||
// status code: 200
|
||||
|
||||
// response headers
|
||||
{
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
// response body content
|
||||
{
|
||||
"success": False,
|
||||
"person": {
|
||||
"name": {
|
||||
"first_name": "Leo",
|
||||
"last_name": "Lee",
|
||||
},
|
||||
"age": 29,
|
||||
"cities": ["Guangzhou", "Shenzhen"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In `extract` and `validate`, we can do chain operation to extract data field in HTTP response.
|
||||
|
||||
For instance, if we want to get `Content-Type` in response headers, then we can specify `headers.content-type`; if we want to get `first_name` in response content, we can specify `content.person.name.first_name`.
|
||||
|
||||
There might be slight difference on list, cos we can use index to locate list item. For example, `Guangzhou` in response content can be specified by `content.person.cities.0`.
|
||||
|
||||
```javascript
|
||||
// get status code
|
||||
status_code
|
||||
|
||||
// get headers field
|
||||
headers.content-type
|
||||
|
||||
// get content field
|
||||
body.success
|
||||
content.success
|
||||
text.success
|
||||
content.person.name.first_name
|
||||
content.person.cities.1
|
||||
```
|
||||
|
||||
```yaml
|
||||
extract:
|
||||
- content_type: headers.content-type
|
||||
- first_name: content.person.name.first_name
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: ["headers.content-type", "application/json"]
|
||||
- gt: ["headers.content-length", 40]
|
||||
- eq: ["content.success", true]
|
||||
- len_eq: ["content.token", 16]
|
||||
```
|
||||
@@ -1,181 +0,0 @@
|
||||
.. default-role:: code
|
||||
|
||||
Write testcases
|
||||
===============
|
||||
|
||||
It is recommended to write testcases in `YAML` format.
|
||||
|
||||
demo
|
||||
----
|
||||
|
||||
And here is testset example of typical scenario: get `token` at the beginning, and each subsequent requests should take the `token` in the headers.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- config:
|
||||
name: "create user testsets."
|
||||
variables:
|
||||
- user_agent: 'iOS/10.3'
|
||||
- device_sn: ${gen_random_string(15)}
|
||||
- os_platform: 'ios'
|
||||
- app_version: '2.8.6'
|
||||
request:
|
||||
base_url: http://127.0.0.1:5000
|
||||
headers:
|
||||
Content-Type: application/json
|
||||
device_sn: $device_sn
|
||||
|
||||
- test:
|
||||
name: get token
|
||||
request:
|
||||
url: /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:
|
||||
- eq: ["status_code", 200]
|
||||
- len_eq: ["content.token", 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:
|
||||
- eq: ["status_code", 201]
|
||||
- eq: ["content.success", true]
|
||||
|
||||
Function invoke is supported in `YAML/JSON` format testcases, such as `gen_random_string` and `get_sign` above. This mechanism relies on the `debugtak.py` hot plugin, with which we can define functions in `debugtak.py` file, and then functions can be auto discovered and invoked in runtime.
|
||||
|
||||
For detailed regulations of writing testcases, you can read the :doc:`quickstart` documents.
|
||||
|
||||
|
||||
Comparator
|
||||
----------
|
||||
|
||||
``HttpRunner`` currently supports the following comparators.
|
||||
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| comparator | Description | A(check), B(expect) | examples |
|
||||
+===========================+===========================+=========================+==========================+
|
||||
| ``eq``, ``==`` | value is equal | A == B | 9 eq 9 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``lt`` | less than | A < B | 7 lt 8 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``le`` | less than or equals | A <= B | 7 le 8, 8 le 8 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``gt`` | greater than | A > B | 8 gt 7 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``ge`` | greater than or equals | A >= B | 8 ge 7, 8 ge 8 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``ne`` | not equals | A != B | 6 ne 9 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``str_eq`` | string equals | str(A) == str(B) | 123 str_eq '123' |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``len_eq``, ``count_eq`` | length or count equals | len(A) == B | | 'abc' len_eq 3 |
|
||||
| | | | | [1,2] len_eq 2 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``len_gt``, ``count_gt`` | length greater than | len(A) > B | | 'abc' len_gt 2 |
|
||||
| | | | | [1,2,3] len_gt 2 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``len_ge``, ``count_ge`` | length greater than | len(A) >= B | | 'abc' len_ge 3 |
|
||||
| | or equals | | | [1,2,3] len_gt 3 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``len_lt``, ``count_lt`` | length less than | len(A) < B | | 'abc' len_lt 4 |
|
||||
| | | | | [1,2,3] len_lt 4 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``len_le``, ``count_le`` | length less than | len(A) <= B | | 'abc' len_le 3 |
|
||||
| | or equals | | | [1,2,3] len_le 3 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``contains`` | contains | [1, 2] contains 1 | | 'abc' contains 'a' |
|
||||
| | | | | [1,2,3] len_lt 4 |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``contained_by`` | contained by | A in B | | 'a' contained_by 'abc' |
|
||||
| | | | | 1 contained_by [1,2] |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``type_match`` | A is instance of B | isinstance(A, B) | 123 type_match 'int' |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``regex_match`` | regex matches | re.match(B, A) | 'abcdef' regex 'a\w+d' |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``startswith`` | starts with | A.startswith(B) is True | 'abc' startswith 'ab' |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
| ``endswith`` | ends with | A.endswith(B) is True | 'abc' endswith 'bc' |
|
||||
+---------------------------+---------------------------+-------------------------+--------------------------+
|
||||
|
||||
|
||||
Extraction and Validation
|
||||
-------------------------
|
||||
|
||||
Suppose we get the following HTTP response.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// status code: 200
|
||||
|
||||
// response headers
|
||||
{
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
// response body content
|
||||
{
|
||||
"success": False,
|
||||
"person": {
|
||||
"name": {
|
||||
"first_name": "Leo",
|
||||
"last_name": "Lee",
|
||||
},
|
||||
"age": 29,
|
||||
"cities": ["Guangzhou", "Shenzhen"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
In `extract` and `validate`, we can do chain operation to extract data field in HTTP response.
|
||||
|
||||
For instance, if we want to get `Content-Type` in response headers, then we can specify `headers.content-type`; if we want to get `first_name` in response content, we can specify `content.person.name.first_name`.
|
||||
|
||||
There might be slight difference on list, cos we can use index to locate list item. For example, `Guangzhou` in response content can be specified by `content.person.cities.0`.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// get status code
|
||||
status_code
|
||||
|
||||
// get headers field
|
||||
headers.content-type
|
||||
|
||||
// get content field
|
||||
body.success
|
||||
content.success
|
||||
text.success
|
||||
content.person.name.first_name
|
||||
content.person.cities.1
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
extract:
|
||||
- content_type: headers.content-type
|
||||
- first_name: content.person.name.first_name
|
||||
validate:
|
||||
- eq: ["status_code", 200]
|
||||
- eq: ["headers.content-type", "application/json"]
|
||||
- gt: ["headers.content-length", 40]
|
||||
- eq: ["content.success", true]
|
||||
- len_eq: ["content.token", 16]
|
||||
|
||||
|
||||
.. _QuickStart: http://
|
||||
Reference in New Issue
Block a user