mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-12 16:01:27 +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]: http://docs.python-requests.org/en/master/
|
||||||
[requests.request]: http://docs.python-requests.org/en/master/api/#requests.request
|
[requests.request]: http://docs.python-requests.org/en/master/api/#requests.request
|
||||||
[comparator]: comparator.md
|
[comparator]: write-testcases.md#comparator
|
||||||
[extraction-and-validation]: extraction-and-validation.md
|
[extraction-and-validation]: write-testcases.md#extraction-and-validation
|
||||||
[quickstart-demo-rev-0]: ../examples/quickstart-demo-rev-0.yml
|
[quickstart-demo-rev-0]: ../examples/quickstart-demo-rev-0.yml
|
||||||
[quickstart-demo-rev-1]: ../examples/quickstart-demo-rev-1.yml
|
[quickstart-demo-rev-1]: ../examples/quickstart-demo-rev-1.yml
|
||||||
[quickstart-demo-rev-2]: ../examples/quickstart-demo-rev-2.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