mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-27 10:31:32 +08:00
1518 lines
54 KiB
HTML
1518 lines
54 KiB
HTML
|
||
|
||
|
||
|
||
<!doctype html>
|
||
<html lang="zh" class="no-js">
|
||
<head>
|
||
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||
|
||
<meta name="description" content="HttpRunner V2.x User Documentation">
|
||
|
||
|
||
|
||
<meta name="author" content="debugtalk">
|
||
|
||
|
||
<meta name="lang:clipboard.copy" content="复制">
|
||
|
||
<meta name="lang:clipboard.copied" content="已复制">
|
||
|
||
<meta name="lang:search.language" content="jp">
|
||
|
||
<meta name="lang:search.pipeline.stopwords" content="True">
|
||
|
||
<meta name="lang:search.pipeline.trimmer" content="True">
|
||
|
||
<meta name="lang:search.result.none" content="没有找到符合条件的结果">
|
||
|
||
<meta name="lang:search.result.one" content="找到 1 个符合条件的结果">
|
||
|
||
<meta name="lang:search.result.other" content="# 个符合条件的结果">
|
||
|
||
<meta name="lang:search.tokenizer" content="[\uff0c\u3002]+">
|
||
|
||
<link rel="shortcut icon" href="../../assets/images/favicon.png">
|
||
<meta name="generator" content="mkdocs-1.0.4, mkdocs-material-4.4.3">
|
||
|
||
|
||
|
||
<title>参数化数据驱动 - HttpRunner V2.x 中文使用文档</title>
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="../../assets/stylesheets/application.30686662.css">
|
||
|
||
<link rel="stylesheet" href="../../assets/stylesheets/application-palette.a8b3c06d.css">
|
||
|
||
|
||
|
||
|
||
<meta name="theme-color" content="#3f51b5">
|
||
|
||
|
||
|
||
<script src="../../assets/javascripts/modernizr.74668098.js"></script>
|
||
|
||
|
||
|
||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
|
||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono&display=fallback">
|
||
<style>body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}</style>
|
||
|
||
|
||
<link rel="stylesheet" href="../../assets/fonts/material-icons.css">
|
||
|
||
|
||
|
||
|
||
|
||
<script>
|
||
window.ga = window.ga || function() {
|
||
(ga.q = ga.q || []).push(arguments)
|
||
}
|
||
ga.l = +new Date
|
||
/* Setup integration and send page view */
|
||
ga("create", "UA-114587036-2", "auto")
|
||
ga("set", "anonymizeIp", true)
|
||
ga("send", "pageview")
|
||
/* Register handler to log search on blur */
|
||
document.addEventListener("DOMContentLoaded", () => {
|
||
if (document.forms.search) {
|
||
var query = document.forms.search.query
|
||
query.addEventListener("blur", function() {
|
||
if (this.value) {
|
||
var path = document.location.pathname;
|
||
ga("send", "pageview", path + "?q=" + this.value)
|
||
}
|
||
})
|
||
}
|
||
})
|
||
</script>
|
||
<script async src="https://www.google-analytics.com/analytics.js"></script>
|
||
|
||
|
||
|
||
</head>
|
||
|
||
|
||
|
||
<body dir="ltr" data-md-color-primary="indigo" data-md-color-accent="indigo">
|
||
|
||
<svg class="md-svg">
|
||
<defs>
|
||
|
||
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="__github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>
|
||
|
||
</defs>
|
||
</svg>
|
||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
|
||
|
||
<a href="#_1" tabindex="1" class="md-skip">
|
||
跳转至
|
||
</a>
|
||
|
||
|
||
<header class="md-header" data-md-component="header">
|
||
<nav class="md-header-nav md-grid">
|
||
<div class="md-flex">
|
||
<div class="md-flex__cell md-flex__cell--shrink">
|
||
<a href="../.." title="HttpRunner V2.x 中文使用文档" class="md-header-nav__button md-logo">
|
||
|
||
<i class="md-icon"></i>
|
||
|
||
</a>
|
||
</div>
|
||
<div class="md-flex__cell md-flex__cell--shrink">
|
||
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
|
||
</div>
|
||
<div class="md-flex__cell md-flex__cell--stretch">
|
||
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
|
||
|
||
<span class="md-header-nav__topic">
|
||
HttpRunner V2.x 中文使用文档
|
||
</span>
|
||
<span class="md-header-nav__topic">
|
||
|
||
参数化数据驱动
|
||
|
||
</span>
|
||
|
||
</div>
|
||
</div>
|
||
<div class="md-flex__cell md-flex__cell--shrink">
|
||
|
||
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
|
||
|
||
<div class="md-search" data-md-component="search" role="dialog">
|
||
<label class="md-search__overlay" for="__search"></label>
|
||
<div class="md-search__inner" role="search">
|
||
<form class="md-search__form" name="search">
|
||
<input type="text" class="md-search__input" name="query" placeholder="搜索" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
|
||
<label class="md-icon md-search__icon" for="__search"></label>
|
||
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">
|
||

|
||
</button>
|
||
</form>
|
||
<div class="md-search__output">
|
||
<div class="md-search__scrollwrap" data-md-scrollfix>
|
||
<div class="md-search-result" data-md-component="result">
|
||
<div class="md-search-result__meta">
|
||
键入以开始搜索
|
||
</div>
|
||
<ol class="md-search-result__list"></ol>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div class="md-flex__cell md-flex__cell--shrink">
|
||
<div class="md-header-nav__source">
|
||
|
||
|
||
|
||
|
||
|
||
<a href="https://github.com/HttpRunner/HttpRunner" title="前往 Github 仓库" class="md-source" data-md-source="github">
|
||
|
||
<div class="md-source__icon">
|
||
<svg viewBox="0 0 24 24" width="24" height="24">
|
||
<use xlink:href="#__github" width="24" height="24"></use>
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="md-source__repository">
|
||
HttpRunner
|
||
</div>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</nav>
|
||
</header>
|
||
|
||
<div class="md-container">
|
||
|
||
|
||
|
||
|
||
<main class="md-main" role="main">
|
||
<div class="md-main__inner md-grid" data-md-component="container">
|
||
|
||
|
||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
|
||
<div class="md-sidebar__scrollwrap">
|
||
<div class="md-sidebar__inner">
|
||
<nav class="md-nav md-nav--primary" data-md-level="0">
|
||
<label class="md-nav__title md-nav__title--site" for="__drawer">
|
||
<a href="../.." title="HttpRunner V2.x 中文使用文档" class="md-nav__button md-logo">
|
||
|
||
<i class="md-icon"></i>
|
||
|
||
</a>
|
||
HttpRunner V2.x 中文使用文档
|
||
</label>
|
||
|
||
<div class="md-nav__source">
|
||
|
||
|
||
|
||
|
||
|
||
<a href="https://github.com/HttpRunner/HttpRunner" title="前往 Github 仓库" class="md-source" data-md-source="github">
|
||
|
||
<div class="md-source__icon">
|
||
<svg viewBox="0 0 24 24" width="24" height="24">
|
||
<use xlink:href="#__github" width="24" height="24"></use>
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="md-source__repository">
|
||
HttpRunner
|
||
</div>
|
||
</a>
|
||
</div>
|
||
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../.." title="介绍" class="md-nav__link">
|
||
介绍
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../Installation/" title="安装说明" class="md-nav__link">
|
||
安装说明
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../quickstart/" title="快速上手" class="md-nav__link">
|
||
快速上手
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item md-nav__item--nested">
|
||
|
||
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-4" type="checkbox" id="nav-4">
|
||
|
||
<label class="md-nav__link" for="nav-4">
|
||
基础概念
|
||
</label>
|
||
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
||
<label class="md-nav__title" for="nav-4">
|
||
基础概念
|
||
</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../concept/nominal/" title="名词解释" class="md-nav__link">
|
||
名词解释
|
||
</a>
|
||
</li>
|
||
|
||
|
||
</ul>
|
||
</nav>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
|
||
|
||
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-5" type="checkbox" id="nav-5" checked>
|
||
|
||
<label class="md-nav__link" for="nav-5">
|
||
测试准备
|
||
</label>
|
||
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
||
<label class="md-nav__title" for="nav-5">
|
||
测试准备
|
||
</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../record/" title="录制生成用例" class="md-nav__link">
|
||
录制生成用例
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../project-structure/" title="项目文件组织" class="md-nav__link">
|
||
项目文件组织
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../testcase-structure/" title="测试用例组织" class="md-nav__link">
|
||
测试用例组织
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../request-hook/" title="hook机制" class="md-nav__link">
|
||
hook机制
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../dot-env/" title="环境变量" class="md-nav__link">
|
||
环境变量
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../testcase-layer/" title="测试用例分层" class="md-nav__link">
|
||
测试用例分层
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item md-nav__item--active">
|
||
|
||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="__toc">
|
||
|
||
|
||
<label class="md-nav__link md-nav__link--active" for="__toc">
|
||
参数化数据驱动
|
||
</label>
|
||
|
||
<a href="./" title="参数化数据驱动" class="md-nav__link md-nav__link--active">
|
||
参数化数据驱动
|
||
</a>
|
||
|
||
|
||
<nav class="md-nav md-nav--secondary">
|
||
|
||
|
||
|
||
<label class="md-nav__title" for="__toc">目录</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_1" class="md-nav__link">
|
||
介绍
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#testsuite" class="md-nav__link">
|
||
测试用例集(testsuite)准备
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_2" class="md-nav__link">
|
||
参数配置概述
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_3" class="md-nav__link">
|
||
参数配置详解
|
||
</a>
|
||
|
||
<nav class="md-nav">
|
||
<ul class="md-nav__list">
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_4" class="md-nav__link">
|
||
独立参数 & 直接指定参数列表
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_5" class="md-nav__link">
|
||
关联参数 & 直接指定参数列表
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#csv" class="md-nav__link">
|
||
独立参数 & 引用 CSV 文件
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#csv_1" class="md-nav__link">
|
||
关联参数 & 引用 CSV 文件
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_6" class="md-nav__link">
|
||
独立参数 & 引用自定义函数
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_7" class="md-nav__link">
|
||
关联参数 & 引用自定义函数
|
||
</a>
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_8" class="md-nav__link">
|
||
参数化运行
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_9" class="md-nav__link">
|
||
案例演示
|
||
</a>
|
||
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
</ul>
|
||
|
||
</nav>
|
||
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../validate-pretty/" title="Validate & Prettify" class="md-nav__link">
|
||
Validate & Prettify
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../security/" title="信息安全" class="md-nav__link">
|
||
信息安全
|
||
</a>
|
||
</li>
|
||
|
||
|
||
</ul>
|
||
</nav>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item md-nav__item--nested">
|
||
|
||
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-6" type="checkbox" id="nav-6">
|
||
|
||
<label class="md-nav__link" for="nav-6">
|
||
测试执行
|
||
</label>
|
||
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
||
<label class="md-nav__title" for="nav-6">
|
||
测试执行
|
||
</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../run-tests/cli/" title="运行测试(CLI)" class="md-nav__link">
|
||
运行测试(CLI)
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../run-tests/report/" title="测试报告" class="md-nav__link">
|
||
测试报告
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../run-tests/load-test/" title="性能测试" class="md-nav__link">
|
||
性能测试
|
||
</a>
|
||
</li>
|
||
|
||
|
||
</ul>
|
||
</nav>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item md-nav__item--nested">
|
||
|
||
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-7" type="checkbox" id="nav-7">
|
||
|
||
<label class="md-nav__link" for="nav-7">
|
||
开发扩展
|
||
</label>
|
||
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
||
<label class="md-nav__title" for="nav-7">
|
||
开发扩展
|
||
</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../development/architecture/" title="Pipline" class="md-nav__link">
|
||
Pipline
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../development/dev-api/" title="基础库调用" class="md-nav__link">
|
||
基础库调用
|
||
</a>
|
||
</li>
|
||
|
||
|
||
</ul>
|
||
</nav>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../FAQ/" title="FAQ" class="md-nav__link">
|
||
FAQ
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item md-nav__item--nested">
|
||
|
||
<input class="md-toggle md-nav__toggle" data-md-toggle="nav-9" type="checkbox" id="nav-9">
|
||
|
||
<label class="md-nav__link" for="nav-9">
|
||
实践案例
|
||
</label>
|
||
<nav class="md-nav" data-md-component="collapsible" data-md-level="1">
|
||
<label class="md-nav__title" for="nav-9">
|
||
实践案例
|
||
</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../examples/testerhome-login/" title="TesterHome 登录" class="md-nav__link">
|
||
TesterHome 登录
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../examples/demo-klook/" title="klook" class="md-nav__link">
|
||
klook
|
||
</a>
|
||
</li>
|
||
|
||
|
||
</ul>
|
||
</nav>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../related-docs/" title="相关资料" class="md-nav__link">
|
||
相关资料
|
||
</a>
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<li class="md-nav__item">
|
||
<a href="../../CHANGELOG/" title="CHANGELOG" class="md-nav__link">
|
||
CHANGELOG
|
||
</a>
|
||
</li>
|
||
|
||
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
|
||
<div class="md-sidebar__scrollwrap">
|
||
<div class="md-sidebar__inner">
|
||
|
||
<nav class="md-nav md-nav--secondary">
|
||
|
||
|
||
|
||
<label class="md-nav__title" for="__toc">目录</label>
|
||
<ul class="md-nav__list" data-md-scrollfix>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_1" class="md-nav__link">
|
||
介绍
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#testsuite" class="md-nav__link">
|
||
测试用例集(testsuite)准备
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_2" class="md-nav__link">
|
||
参数配置概述
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_3" class="md-nav__link">
|
||
参数配置详解
|
||
</a>
|
||
|
||
<nav class="md-nav">
|
||
<ul class="md-nav__list">
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_4" class="md-nav__link">
|
||
独立参数 & 直接指定参数列表
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_5" class="md-nav__link">
|
||
关联参数 & 直接指定参数列表
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#csv" class="md-nav__link">
|
||
独立参数 & 引用 CSV 文件
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#csv_1" class="md-nav__link">
|
||
关联参数 & 引用 CSV 文件
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_6" class="md-nav__link">
|
||
独立参数 & 引用自定义函数
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_7" class="md-nav__link">
|
||
关联参数 & 引用自定义函数
|
||
</a>
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
</nav>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_8" class="md-nav__link">
|
||
参数化运行
|
||
</a>
|
||
|
||
</li>
|
||
|
||
<li class="md-nav__item">
|
||
<a href="#_9" class="md-nav__link">
|
||
案例演示
|
||
</a>
|
||
|
||
</li>
|
||
|
||
|
||
|
||
|
||
|
||
</ul>
|
||
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<div class="md-content">
|
||
<article class="md-content__inner md-typeset">
|
||
|
||
|
||
|
||
<h1>参数化数据驱动</h1>
|
||
|
||
<h2 id="_1">介绍<a class="headerlink" href="#_1" title="Permanent link">¶</a></h2>
|
||
<p>在自动化测试中,经常会遇到如下场景:</p>
|
||
<ul>
|
||
<li>测试搜索功能,只有一个搜索输入框,但有 10 种不同类型的搜索关键字;</li>
|
||
<li>测试账号登录功能,需要输入用户名和密码,按照等价类划分后有 20 种组合情况。</li>
|
||
</ul>
|
||
<p>这里只是随意找了两个典型的例子,相信大家都有遇到过很多类似的场景。总结下来,就是在我们的自动化测试脚本中存在参数,并且我们需要采用不同的参数去运行。</p>
|
||
<p>经过概括,参数基本上分为两种类型:</p>
|
||
<ul>
|
||
<li>单个独立参数:例如前面的第一种场景,我们只需要变换搜索关键字这一个参数</li>
|
||
<li>多个具有关联性的参数:例如前面的第二种场景,我们需要变换用户名和密码两个参数,并且这两个参数需要关联组合</li>
|
||
</ul>
|
||
<p>然后,对于参数而言,我们可能具有一个参数列表,在脚本运行时需要按照不同的规则去取值,例如顺序取值、随机取值、循环取值等等。</p>
|
||
<p>这就是典型的参数化和数据驱动。</p>
|
||
<p>如需了解 HttpRunner 参数化数据驱动机制的实现原理和技术细节,可前往阅读<a href="http://debugtalk.com/post/httprunner-data-driven/">《HttpRunner 实现参数化数据驱动机制》</a>。</p>
|
||
<h2 id="testsuite">测试用例集(testsuite)准备<a class="headerlink" href="#testsuite" title="Permanent link">¶</a></h2>
|
||
<p>从 2.0.0 版本开始,HttpRunner 不再支持在测试用例文件中进行参数化配置;参数化的功能需要在 testsuite 中实现。变更的目的是让测试用例(testcase)的概念更纯粹,关于测试用例和测试用例集的概念定义,详见<a href="/prepare/parameters/">《测试用例组织》</a>。</p>
|
||
<p>参数化机制需要在测试用例集(testsuite)中实现。如需实现数据驱动机制,需要创建一个 testsuite,在 testsuite 中引用测试用例,并定义参数化配置。</p>
|
||
<p>测试用例集(testsuite)的格式如下所示:</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">testsuite description</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
|
||
<span class="nt">testcase2_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase2</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>需要注意的是,testsuite 和 testcase 的格式存在较大区别,详见<a href="/prepare/testcase-structure/">《测试用例组织》</a>。</p>
|
||
<h2 id="_2">参数配置概述<a class="headerlink" href="#_2" title="Permanent link">¶</a></h2>
|
||
<p>如需对某测试用例(testcase)实现参数化数据驱动,需要使用 <code>parameters</code> 关键字,定义参数名称并指定数据源取值方式。</p>
|
||
<p>参数名称的定义分为两种情况:</p>
|
||
<ul>
|
||
<li>独立参数单独进行定义;</li>
|
||
<li>多个参数具有关联性的参数需要将其定义在一起,采用短横线(<code>-</code>)进行连接。</li>
|
||
</ul>
|
||
<p>数据源指定支持三种方式:</p>
|
||
<ul>
|
||
<li>在 YAML/JSON 中直接指定参数列表:该种方式最为简单易用,适合参数列表比较小的情况</li>
|
||
<li>通过内置的 parameterize(可简写为P)函数引用 CSV 文件:该种方式需要准备 CSV 数据文件,适合数据量比较大的情况</li>
|
||
<li>调用 debugtalk.py 中自定义的函数生成参数列表:该种方式最为灵活,可通过自定义 Python 函数实现任意场景的数据驱动机制,当需要动态生成参数列表时也需要选择该种方式</li>
|
||
</ul>
|
||
<p>三种方式可根据实际项目需求进行灵活选择,同时支持多种方式的组合使用。假如测试用例中定义了多个参数,那么测试用例在运行时会对参数进行笛卡尔积组合,覆盖所有参数组合情况。</p>
|
||
<p>使用方式概览如下:</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">user_agent</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="s">"iOS/10.1"</span><span class="p p-Indicator">,</span> <span class="s">"iOS/10.2"</span><span class="p p-Indicator">,</span> <span class="s">"iOS/10.3"</span><span class="p p-Indicator">]</span>
|
||
<span class="nt">user_id</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${P(user_id.csv)}</span>
|
||
<span class="nt">username-password</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${get_account(10)}</span>
|
||
</pre></div>
|
||
|
||
|
||
<h2 id="_3">参数配置详解<a class="headerlink" href="#_3" title="Permanent link">¶</a></h2>
|
||
<p>将参数名称定义和数据源指定方式进行组合,共有 6 种形式。现分别针对每一类情况进行详细说明。</p>
|
||
<h3 id="_4">独立参数 & 直接指定参数列表<a class="headerlink" href="#_4" title="Permanent link">¶</a></h3>
|
||
<p>对于参数列表比较小的情况,最简单的方式是直接在 YAML/JSON 中指定参数列表内容。</p>
|
||
<p>例如,对于独立参数 <code>user_id</code>,参数列表为 <code>[1001, 1002, 1003, 1004]</code>,那么就可以按照如下方式进行配置:</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">testcase description</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">create user</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">demo-quickstart-6.yml</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">user_id</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="nv">1001</span><span class="p p-Indicator">,</span> <span class="nv">1002</span><span class="p p-Indicator">,</span> <span class="nv">1003</span><span class="p p-Indicator">,</span> <span class="nv">1004</span><span class="p p-Indicator">]</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>进行该配置后,测试用例在运行时就会对 user_id 实现数据驱动,即分别使用 <code>[1001, 1002, 1003, 1004]</code> 四个值运行测试用例。</p>
|
||
<details>
|
||
<summary>点击查看运行日志</summary>
|
||
|
||
<div class="codehilite"><pre><span></span>$ hrun docs/data/demo-quickstart-7.json
|
||
INFO Start to run testcase: create user 1001
|
||
/api/get-token
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 8.95 ms, response_length: 46 bytes
|
||
|
||
.
|
||
/api/users/1001
|
||
INFO POST http://127.0.0.1:5000/api/users/1001
|
||
INFO status_code: 201, response_time(ms): 3.02 ms, response_length: 54 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 2 tests in 0.021s
|
||
|
||
OK
|
||
INFO Start to run testcase: create user 1002
|
||
/api/get-token
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 2.78 ms, response_length: 46 bytes
|
||
|
||
.
|
||
/api/users/1002
|
||
INFO POST http://127.0.0.1:5000/api/users/1002
|
||
INFO status_code: 201, response_time(ms): 2.84 ms, response_length: 54 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 2 tests in 0.007s
|
||
|
||
OK
|
||
INFO Start to run testcase: create user 1003
|
||
/api/get-token
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 2.92 ms, response_length: 46 bytes
|
||
|
||
.
|
||
/api/users/1003
|
||
INFO POST http://127.0.0.1:5000/api/users/1003
|
||
INFO status_code: 201, response_time(ms): 5.56 ms, response_length: 54 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 2 tests in 0.011s
|
||
|
||
OK
|
||
INFO Start to run testcase: create user 1004
|
||
/api/get-token
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 5.25 ms, response_length: 46 bytes
|
||
|
||
.
|
||
/api/users/1004
|
||
INFO POST http://127.0.0.1:5000/api/users/1004
|
||
INFO status_code: 201, response_time(ms): 7.02 ms, response_length: 54 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 2 tests in 0.016s
|
||
|
||
OK
|
||
INFO Start to render Html report ...
|
||
INFO Generated Html report: /Users/debugtalk/MyProjects/HttpRunner-dev/httprunner-docs-v2x/reports/1548518757.html
|
||
</pre></div>
|
||
|
||
|
||
|
||
</details>
|
||
|
||
<p>可以看出,测试用例总共运行了 4 次,并且每次运行时都是采用的不同 user_id。</p>
|
||
<h3 id="_5">关联参数 & 直接指定参数列表<a class="headerlink" href="#_5" title="Permanent link">¶</a></h3>
|
||
<p>对于具有关联性的多个参数,例如 username 和 password,那么就可以按照如下方式进行配置:</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">username-password</span><span class="p">:</span>
|
||
<span class="p p-Indicator">-</span> <span class="p p-Indicator">[</span><span class="s">"user1"</span><span class="p p-Indicator">,</span> <span class="s">"111111"</span><span class="p p-Indicator">]</span>
|
||
<span class="p p-Indicator">-</span> <span class="p p-Indicator">[</span><span class="s">"user2"</span><span class="p p-Indicator">,</span> <span class="s">"222222"</span><span class="p p-Indicator">]</span>
|
||
<span class="p p-Indicator">-</span> <span class="p p-Indicator">[</span><span class="s">"user3"</span><span class="p p-Indicator">,</span> <span class="s">"333333"</span><span class="p p-Indicator">]</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>进行该配置后,测试用例在运行时就会对 username 和 password 实现数据驱动,即分别使用 <code>{"username": "user1", "password": "111111"}</code>、<code>{"username": "user2", "password": "222222"}</code>、<code>{"username": "user3", "password": "333333"}</code> 运行 3 次测试,并且保证参数值总是成对使用。</p>
|
||
<h3 id="csv">独立参数 & 引用 CSV 文件<a class="headerlink" href="#csv" title="Permanent link">¶</a></h3>
|
||
<p>对于已有参数列表,并且数据量比较大的情况,比较适合的方式是将参数列表值存储在 CSV 数据文件中。</p>
|
||
<p>对于 CSV 数据文件,需要遵循如下几项约定的规则:</p>
|
||
<ul>
|
||
<li>CSV 文件中的第一行必须为参数名称,从第二行开始为参数值,每个(组)值占一行;</li>
|
||
<li>若同一个 CSV 文件中具有多个参数,则参数名称和数值的间隔符需实用英文逗号;</li>
|
||
<li>在 YAML/JSON 文件引用 CSV 文件时,文件路径为基于项目根目录(debugtalk.py 所在路径)的相对路径。</li>
|
||
</ul>
|
||
<p>例如,user_id 的参数取值范围为 1001~2000,那么我们就可以创建 user_id.csv,并且在文件中按照如下形式进行描述。</p>
|
||
<div class="codehilite"><pre><span></span>user_id
|
||
1001
|
||
1002
|
||
...
|
||
1999
|
||
2000
|
||
</pre></div>
|
||
|
||
|
||
<p>然后在 YAML/JSON 测试用例文件中,就可以通过内置的 <code>parameterize</code>(可简写为 <code>P</code>)函数引用 CSV 文件。</p>
|
||
<p>假设项目的根目录下有 data 文件夹,user_id.csv 位于其中,那么 user_id.csv 的引用描述如下:</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">user_id</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${P(data/user_id.csv)}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>即 <code>P</code> 函数的参数(CSV 文件路径)是相对于项目根目录的相对路径。当然,这里也可以使用 CSV 文件在系统中的绝对路径,不过这样的话在项目路径变动时就会出现问题,因此推荐使用相对路径的形式。</p>
|
||
<h3 id="csv_1">关联参数 & 引用 CSV 文件<a class="headerlink" href="#csv_1" title="Permanent link">¶</a></h3>
|
||
<p>对于具有关联性的多个参数,例如 username 和 password,那么就可以创建 <a href="/data/account.csv">account.csv</a>,并在文件中按照如下形式进行描述。</p>
|
||
<div class="codehilite"><pre><span></span>username,password
|
||
test1,111111
|
||
test2,222222
|
||
test3,333333
|
||
</pre></div>
|
||
|
||
|
||
<p>然后在 YAML/JSON 测试用例文件中,就可以通过内置的 <code>parameterize</code>(可简写为 <code>P</code>)函数引用 CSV 文件。</p>
|
||
<p>假设项目的根目录下有 data 文件夹,account.csv 位于其中,那么 account.csv 的引用描述如下:</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">username-password</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${P(data/account.csv)}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>需要说明的是,在 parameters 中指定的参数名称必须与 CSV 文件中第一行的参数名称一致,顺序可以不一致,参数个数也可以不一致。</p>
|
||
<p>例如,在 <a href="/data/account.csv">account.csv</a> 文件中可以包含多个参数,username、password、phone、age:</p>
|
||
<div class="codehilite"><pre><span></span>username,password,phone,age
|
||
test1,111111,18600000001,21
|
||
test2,222222,18600000002,22
|
||
test3,333333,18600000003,23
|
||
</pre></div>
|
||
|
||
|
||
<p>而在 YAML/JSON 测试用例文件中指定参数时,可以只使用部分参数,并且参数顺序无需与 CSV 文件中参数名称的顺序一致。</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">phone-username</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${P(account.csv)}</span>
|
||
</pre></div>
|
||
|
||
|
||
<h3 id="_6">独立参数 & 引用自定义函数<a class="headerlink" href="#_6" title="Permanent link">¶</a></h3>
|
||
<p>对于没有现成参数列表,或者需要更灵活的方式动态生成参数的情况,可以通过在 debugtalk.py 中自定义函数生成参数列表,并在 YAML/JSON 引用自定义函数的方式。</p>
|
||
<p>例如,若需对 user_id 进行参数化数据驱动,参数取值范围为 1001~1004,那么就可以在 debugtalk.py 中定义一个函数,返回参数列表。</p>
|
||
<div class="codehilite"><pre><span></span><span class="k">def</span> <span class="nf">get_user_id</span><span class="p">():</span>
|
||
<span class="k">return</span> <span class="p">[</span>
|
||
<span class="p">{</span><span class="s2">"user_id"</span><span class="p">:</span> <span class="mi">1001</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"user_id"</span><span class="p">:</span> <span class="mi">1002</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"user_id"</span><span class="p">:</span> <span class="mi">1003</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"user_id"</span><span class="p">:</span> <span class="mi">1004</span><span class="p">}</span>
|
||
<span class="p">]</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>然后,在 YAML/JSON 的 parameters 中就可以通过调用自定义函数的形式来指定数据源。</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">user_id</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${get_user_id()}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>另外,通过函数的传参机制,还可以实现更灵活的参数生成功能,在调用函数时指定需要生成的参数个数。</p>
|
||
<h3 id="_7">关联参数 & 引用自定义函数<a class="headerlink" href="#_7" title="Permanent link">¶</a></h3>
|
||
<p>对于具有关联性的多个参数,实现方式也类似。</p>
|
||
<p>例如,在 debugtalk.py 中定义函数 get_account,生成指定数量的账号密码参数列表。</p>
|
||
<div class="codehilite"><pre><span></span><span class="k">def</span> <span class="nf">get_account</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
|
||
<span class="n">accounts</span> <span class="o">=</span> <span class="p">[]</span>
|
||
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">num</span><span class="o">+</span><span class="mi">1</span><span class="p">):</span>
|
||
<span class="n">accounts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
||
<span class="p">{</span><span class="s2">"username"</span><span class="p">:</span> <span class="s2">"user</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">index</span><span class="p">,</span> <span class="s2">"password"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">index</span><span class="p">)</span> <span class="o">*</span> <span class="mi">6</span><span class="p">},</span>
|
||
<span class="p">)</span>
|
||
|
||
<span class="k">return</span> <span class="n">accounts</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>那么在 YAML/JSON 的 parameters 中就可以调用自定义函数生成指定数量的参数列表。</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="s">"demo"</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="nt">testcase1_name</span><span class="p">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/path/to/testcase1</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">username-password</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${get_account(10)}</span>
|
||
</pre></div>
|
||
|
||
|
||
<blockquote>
|
||
<p>需要注意的是,在自定义函数中,生成的参数列表必须为 <code>list of dict</code> 的数据结构,该设计主要是为了与 CSV 文件的处理机制保持一致。</p>
|
||
</blockquote>
|
||
<h2 id="_8">参数化运行<a class="headerlink" href="#_8" title="Permanent link">¶</a></h2>
|
||
<p>完成以上参数定义和数据源准备工作之后,参数化运行与普通测试用例的运行完全一致。</p>
|
||
<p>采用 hrun 命令运行自动化测试:</p>
|
||
<div class="codehilite"><pre><span></span>$ hrun tests/data/demo_parameters.yml
|
||
</pre></div>
|
||
|
||
|
||
<p>采用 locusts 命令运行性能测试:</p>
|
||
<div class="codehilite"><pre><span></span>$ locusts -f tests/data/demo_parameters.yml
|
||
</pre></div>
|
||
|
||
|
||
<p>区别在于,自动化测试时遍历一遍后会终止执行,性能测试时每个并发用户都会循环遍历所有参数。</p>
|
||
<h2 id="_9">案例演示<a class="headerlink" href="#_9" title="Permanent link">¶</a></h2>
|
||
<p>假设我们有一个获取 token 的<a href="/data/demo-testcase-get-token.yml">测试用例</a>。</p>
|
||
<details>
|
||
<summary>点击查看 YAML 测试用例</summary>
|
||
|
||
<div class="codehilite"><pre><span></span><span class="p p-Indicator">-</span> <span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">get token</span>
|
||
<span class="nt">base_url</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">http://127.0.0.1:5000</span>
|
||
<span class="nt">variables</span><span class="p">:</span>
|
||
<span class="nt">device_sn</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${gen_random_string(15)}</span>
|
||
<span class="nt">os_platform</span><span class="p">:</span> <span class="s">'ios'</span>
|
||
<span class="nt">app_version</span><span class="p">:</span> <span class="s">'2.8.6'</span>
|
||
|
||
<span class="p p-Indicator">-</span> <span class="nt">test</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">get token with $device_sn, $os_platform, $app_version</span>
|
||
<span class="nt">request</span><span class="p">:</span>
|
||
<span class="nt">headers</span><span class="p">:</span>
|
||
<span class="nt">Content-Type</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">application/json</span>
|
||
<span class="nt">User-Agent</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">python-requests/2.18.4</span>
|
||
<span class="nt">app_version</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">$app_version</span>
|
||
<span class="nt">device_sn</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">$device_sn</span>
|
||
<span class="nt">os_platform</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">$os_platform</span>
|
||
<span class="nt">json</span><span class="p">:</span>
|
||
<span class="nt">sign</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${get_sign($device_sn, $os_platform, $app_version)}</span>
|
||
<span class="nt">method</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">POST</span>
|
||
<span class="nt">url</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">/api/get-token</span>
|
||
<span class="nt">extract</span><span class="p">:</span>
|
||
<span class="nt">token</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">content.token</span>
|
||
<span class="nt">validate</span><span class="p">:</span>
|
||
<span class="p p-Indicator">-</span> <span class="nt">eq</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="nv">status_code</span><span class="p p-Indicator">,</span> <span class="nv">200</span><span class="p p-Indicator">]</span>
|
||
<span class="p p-Indicator">-</span> <span class="nt">eq</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="nv">headers.Content-Type</span><span class="p p-Indicator">,</span> <span class="nv">application/json</span><span class="p p-Indicator">]</span>
|
||
<span class="p p-Indicator">-</span> <span class="nt">eq</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="nv">content.success</span><span class="p p-Indicator">,</span> <span class="nv">true</span><span class="p p-Indicator">]</span>
|
||
</pre></div>
|
||
|
||
|
||
</details>
|
||
|
||
<p>如果我们需要使用 device_sn、app_version 和 os_platform 这三个参数来进行参数化数据驱动,那么就可以创建一个 <a href="/data/demo-parameters-get-token.yml">testsuite</a>,并且进行参数化配置。</p>
|
||
<div class="codehilite"><pre><span></span><span class="nt">config</span><span class="p">:</span>
|
||
<span class="nt">name</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">get token with parameters</span>
|
||
|
||
<span class="nt">testcases</span><span class="p">:</span>
|
||
<span class="l l-Scalar l-Scalar-Plain">get token with $user_agent, $app_version, $os_platform</span><span class="p p-Indicator">:</span>
|
||
<span class="nt">testcase</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">demo-testcase-get-token.yml</span>
|
||
<span class="nt">parameters</span><span class="p">:</span>
|
||
<span class="nt">user_agent</span><span class="p">:</span> <span class="p p-Indicator">[</span><span class="s">"iOS/10.1"</span><span class="p p-Indicator">,</span> <span class="s">"iOS/10.2"</span><span class="p p-Indicator">,</span> <span class="s">"iOS/10.3"</span><span class="p p-Indicator">]</span>
|
||
<span class="nt">app_version</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${P(app_version.csv)}</span>
|
||
<span class="nt">os_platform</span><span class="p">:</span> <span class="l l-Scalar l-Scalar-Plain">${get_os_platform()}</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>其中,<code>user_agent</code> 使用了直接指定参数列表的形式。</p>
|
||
<p><a href="/data/app_version.csv">app_version</a> 通过 CSV 文件进行参数配置,对应的文件内容为:</p>
|
||
<div class="codehilite"><pre><span></span>app_version
|
||
2.8.5
|
||
2.8.6
|
||
</pre></div>
|
||
|
||
|
||
<p>os_platform 使用自定义函数的形式生成参数列表,对应的函数内容为:</p>
|
||
<div class="codehilite"><pre><span></span><span class="k">def</span> <span class="nf">get_os_platform</span><span class="p">():</span>
|
||
<span class="k">return</span> <span class="p">[</span>
|
||
<span class="p">{</span><span class="s2">"os_platform"</span><span class="p">:</span> <span class="s2">"ios"</span><span class="p">},</span>
|
||
<span class="p">{</span><span class="s2">"os_platform"</span><span class="p">:</span> <span class="s2">"android"</span><span class="p">}</span>
|
||
<span class="p">]</span>
|
||
</pre></div>
|
||
|
||
|
||
<p>那么,经过笛卡尔积组合,应该总共有 <code>3*2*2=12</code> 种参数组合情况。</p>
|
||
<details>
|
||
<summary>点击查看完整运行日志</summary>
|
||
|
||
<div class="codehilite"><pre><span></span>$ hrun docs/data/demo-parameters-get-token.yml
|
||
INFO Start to run testcase: get token with iOS/10.1, 2.8.5, ios
|
||
get token with PBJda7SXM2ReWlu, ios, 2.8.5
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 10.66 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.026s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.1, 2.8.5, android
|
||
get token with PBJda7SXM2ReWlu, android, 2.8.5
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 3.03 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.004s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.1, 2.8.6, ios
|
||
get token with PBJda7SXM2ReWlu, ios, 2.8.6
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 10.76 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.012s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.1, 2.8.6, android
|
||
get token with PBJda7SXM2ReWlu, android, 2.8.6
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 4.49 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.006s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.2, 2.8.5, ios
|
||
get token with PBJda7SXM2ReWlu, ios, 2.8.5
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 4.39 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.006s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.2, 2.8.5, android
|
||
get token with PBJda7SXM2ReWlu, android, 2.8.5
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 4.04 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.005s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.2, 2.8.6, ios
|
||
get token with PBJda7SXM2ReWlu, ios, 2.8.6
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 3.44 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.004s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.2, 2.8.6, android
|
||
get token with PBJda7SXM2ReWlu, android, 2.8.6
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 4.03 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.005s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.3, 2.8.5, ios
|
||
get token with PBJda7SXM2ReWlu, ios, 2.8.5
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 5.14 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.008s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.3, 2.8.5, android
|
||
get token with PBJda7SXM2ReWlu, android, 2.8.5
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 7.62 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.010s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.3, 2.8.6, ios
|
||
get token with PBJda7SXM2ReWlu, ios, 2.8.6
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 4.88 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.006s
|
||
|
||
OK
|
||
INFO Start to run testcase: get token with iOS/10.3, 2.8.6, android
|
||
get token with PBJda7SXM2ReWlu, android, 2.8.6
|
||
INFO POST http://127.0.0.1:5000/api/get-token
|
||
INFO status_code: 200, response_time(ms): 5.41 ms, response_length: 46 bytes
|
||
|
||
.
|
||
|
||
----------------------------------------------------------------------
|
||
Ran 1 test in 0.008s
|
||
|
||
OK
|
||
INFO Start to render Html report ...
|
||
INFO Generated Html report: /Users/debugtalk/MyProjects/HttpRunner-dev/httprunner-docs-v2x/reports/1551950193.html
|
||
</pre></div>
|
||
|
||
|
||
</details>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
|
||
<footer class="md-footer">
|
||
|
||
<div class="md-footer-nav">
|
||
<nav class="md-footer-nav__inner md-grid">
|
||
|
||
<a href="../testcase-layer/" title="测试用例分层" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
|
||
<div class="md-flex__cell md-flex__cell--shrink">
|
||
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
|
||
</div>
|
||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
||
<span class="md-flex__ellipsis">
|
||
<span class="md-footer-nav__direction">
|
||
上一页
|
||
</span>
|
||
测试用例分层
|
||
</span>
|
||
</div>
|
||
</a>
|
||
|
||
|
||
<a href="../validate-pretty/" title="Validate & Prettify" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
|
||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
||
<span class="md-flex__ellipsis">
|
||
<span class="md-footer-nav__direction">
|
||
下一页
|
||
</span>
|
||
Validate & Prettify
|
||
</span>
|
||
</div>
|
||
<div class="md-flex__cell md-flex__cell--shrink">
|
||
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
|
||
</div>
|
||
</a>
|
||
|
||
</nav>
|
||
</div>
|
||
|
||
<div class="md-footer-meta md-typeset">
|
||
<div class="md-footer-meta__inner md-grid">
|
||
<div class="md-footer-copyright">
|
||
|
||
<div class="md-footer-copyright__highlight">
|
||
Copyright © 2017 - 2019 debugtalk
|
||
</div>
|
||
|
||
powered by
|
||
<a href="https://www.mkdocs.org">MkDocs</a>
|
||
and
|
||
<a href="https://squidfunk.github.io/mkdocs-material/">
|
||
Material for MkDocs</a>
|
||
</div>
|
||
|
||
<div class="md-footer-social">
|
||
<link rel="stylesheet" href="../../assets/fonts/font-awesome.css">
|
||
|
||
<a href="https://debugtalk.com" class="md-footer-social__link fa fa-globe"></a>
|
||
|
||
<a href="https://github.com/httprunner" class="md-footer-social__link fa fa-github"></a>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
|
||
</div>
|
||
|
||
<script src="../../assets/javascripts/application.ac79c3b0.js"></script>
|
||
|
||
|
||
|
||
|
||
<script src="../../assets/javascripts/lunr/lunr.stemmer.support.js"></script>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<script>app.initialize({version:"1.0.4",url:{base:"../.."}})</script>
|
||
|
||
<script src="../../js/slardar.js"></script>
|
||
|
||
|
||
</body>
|
||
</html> |