单元测试

也许你经常需要对你的的应用进行单元测试或者仅仅检查 Python session 的输出。理论上讲这是很简单的,你可以伪造一个环境,通过一个假的 start_response 遍历应用,但是这里还有一个更好的方法。

Diving In

Werkzeug 提供了一个 Client 对象,可以传入一个 WSGI 应用(可选传入一个 response),通过这个你可以向应用发出一个虚拟请求。

用三个参数调用一个 response: 应用迭代器、状态和一个 headers。默认 response 返回一个元组。因为 response 对象有相同的签名,所以你可以像使用 response 一样使用他们。通过这样一种方式进行测试功能是很理想的。

  1. >>> from werkzeug.test import Client
  2. >>> from werkzeug.testapp import test_app
  3. >>> from werkzeug.wrappers import BaseResponse
  4. >>> c = Client(test_app, BaseResponse)
  5. >>> resp = c.get('/')
  6. >>> resp.status_code
  7. 200
  8. >>> resp.headers
  9. Headers([('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', '8339')])
  10. >>> resp.data.splitlines()[0]
  11. '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"'

或默认没有 response:

  1. >>> c = Client(test_app)
  2. >>> app_iter, status, headers = c.get('/')
  3. >>> status
  4. '200 OK'
  5. >>> headers
  6. [('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', '8339')]
  7. >>> ''.join(app_iter).splitlines()[0]
  8. '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"'

环境搭建

0.5 新版功能.

交互测试应用 最简单的方法是使用 EnvironBuilder 类。它可以创建标准 WSGI环境和请求对象。

下面的例子创建了一个上传文件和文件表单的 WSGI 环境:

  1. >>> from werkzeug.test import EnvironBuilder
  2. >>> from StringIO import StringIO
  3. >>> builder = EnvironBuilder(method='POST', data={'foo': 'this is some text',
  4. ... 'file': (StringIO('my file contents'), 'test.txt')})
  5. >>> env = builder.get_environ()

返回的环境是一个新的 WSGI 环境,可用于进一步的处理:

  1. >>> from werkzeug.wrappers import Request
  2. >>> req = Request(env)
  3. >>> req.form['foo']
  4. u'this is some text'
  5. >>> req.files['file']
  6. <FileStorage: u'test.txt' ('text/plain')>
  7. >>> req.files['file'].read()
  8. 'my file contents'

当你将一个字典传给构造函数数据, EnvironBuilder 会自动自动找出内容类型。如过你传的似乎一个字符串或者输入字符流,你不得不自己来做这些处理。

默认地它将会尝试使用 application/x-www-form-urlencoded ,如果文件被上传则只使用 multipart/form-data :

  1. >>> builder = EnvironBuilder(method='POST', data={'foo': 'bar'})
  2. >>> builder.content_type
  3. 'application/x-www-form-urlencoded'
  4. >>> builder.files['foo'] = StringIO('contents')
  5. >>> builder.content_type
  6. 'multipart/form-data'

如果传入一个字符串(或一个输入流),你必须自己指定内容的类型:

  1. >>> builder = EnvironBuilder(method='POST', data='{"json": "this is"}')
  2. >>> builder.content_type
  3. >>> builder.content_type = 'application/json'

测试 API

  • class _tests.EnvironBuilder(_path='/', base_url=None, query_string=None, method='GET', input_stream=None, content_type=None, content_length=None, errors_stream=None, multithread=False, multiprocess=False, run_once=False, headers=None, data=None, environ_base=None, environ_overrides=None, charset='utf-8')
  • 这个类为了测试可以方便的创建一个 WSGI 环境。他可以从任意数据快速创建 WSGI环境或请求对象。

这个类的签名也可用于 Werkzeug 的其他地方(create_environ(), BaseResponse.from_values(), Client.open())。因为大多数功能只可通过构造函数实现。

文件和表格数据可以被各自的 form 和 files 属性独立处理。但是以相同的参数传入构造函数:data

data 可以是这些值:

  • a str: 如果一个字符串被转化为一个 input_stream,将会设置content_length ,你还要提供一个 content_type
  • a dict: 如果是一个字典,键将是一个字符串,值是以下对象:
    • 一个 file-like 对象。他们会被自动转化成 FileStorage 对象。
    • 一个元组。 add_file() 方法调用元组项目作为参数。

0.6 新版功能: pathbase_url 现在是 unicode 字符串,它可以使用 iri_to_uri()函数编码。

参数:

  • path – 请求的路径。在 WSGI 环境它等效于 PATH_INFO。如果 query_string没有被定义,这里有一个问题要注意,path 后面的将被当作 query string
  • base_url – base URL 是一个用于提取 WSGI URL ,主机 (服务器名 + 服务端口)和根脚本的 (SCRIPT_NAME) 的 URL。
  • query_string – URL 参数可选的字符串和字典。
  • method – HTTP 方法,默认为 GET
  • input_stream – 一个可选输入流。不要指定它,一旦输入流被设定,你将不能更改 args 属性和 files 属性除非你将input_stream 重新设为 None
  • content_type – 请求的内容类型。在0.5 版本当你指定文件和表格数据的时候不必必须指定他。
  • content_length – 请求的内容长度。当通过 data 提供数据不必必须指定他。
  • errors_stream – 用于 wsgi.errors 可选的错误流。默认为 stderr。
  • multithread – 控制 wsgi.multithread。默认为 False
  • multiprocess – 控制 wsgi.multiprocess。默认为 False
  • run_once – 控制 wsgi.run_once。默认为 False
  • headers – headers 一个可选的列表或者 Headers 对象。
  • data – 一个字符串或者表单数据字典。看上边的 explanation。
  • environ_base – 一个可选的默认环境。
  • environ_overrides – 一个可选的覆盖环境。
  • charset – 编码 unicode 数据的字符集。
  • path
  • 应用的地址。(又叫 PATH_INFO)

  • charset

  • 编码 unicode 数据的字符集。

  • headers

  • 一个带着请求 headers的 Headers 对象。

  • errors_stream

  • 用于 wsgi.errors 流的错误流。

  • multithread

  • wsgi.multithread 的值。

  • multiprocess

  • wsgi.multiprocess 的值。

  • environ_base

  • 新创建环境的基本字典。

  • environ_overrides

  • 用于覆盖生成环境的带值字典。

  • input_stream

  • 可选选项输入流。这个和 form / files 是相互独立的。同时如果请求方法不是 POST / PUT 或其他类似方法,不要提供输入流。

  • args

  • URL 参数是 MultiDict。

  • base_url

  • base URL 是一个用于提取 WSGI URL ,主机(服务器名 + 服务器端口) 和根脚本 (SCRIPT_NAME) 的 URL

  • close()

  • 关闭所有文件。如果把 file 对象放入 files 字典,你可以通过调用这个方法自动关闭他们。

  • content_length

  • 整数的长度,反射给 headers。如果你设置了 files 或 form属性不要设置这个参数。

  • content_type

  • 请求的内容类型。反射给 headers。如果你设置了 files 和form 属性就不能设置内容类型。

  • get_environ()

  • 返回内置环境。

  • getrequest(_cls=None)

  • 返回一个带数据的请求。如果没有指定请求类,将会是用 request_class

参数:cls – 使用 request 包装。

  • input_stream
  • 一个可选的输入流。如果你设置它,将会清空 form 和 files。

  • query_string

  • 查询字符串。如果你设置它, args 属性将不再可用。

  • request_class

  • 默认的请求类 get_request()

BaseRequest 的别名

  • server_name
  • 服务器名 (只读, 使用 host 设置)

  • server_port

  • 整型服务器接口(只读,使用 host 设置)

  • serverprotocol = 'HTTP/1.1'_

  • 服务器使用协议。默认为 HTTP/1.1

  • wsgiversion = (1, 0)_

  • 使用的 WSGI 版本。默认为(1, 0)。
  • class _tests.Client(_application, response_wrapper=None, use_cookies=True, allow_subdomain_redirects=False)
  • 这个类允许你发送请求给一个包裹的应用。

响应可以是一个类或者一个有三个参数工厂函数: app_iter, status and headers。默认的响应仅仅是一个元组。

例如:

  1. class ClientResponse(BaseResponse):
  2. ...
  3. client = Client(MyApplication(), response_wrapper=ClientResponse)

use_cookies 参数默认是开启的,无论 cookies 是否被存储,他都会和请求一起传输。但是你也可以关闭 cookie。

如果你想要请求应用的子域名,你可以设置 allow_subdomain_redirectsTrue ,如果为 False ,将不允许外部重定向。

0.5 新版功能: use_cookies 是在这个版本添加的。老版本不提供内置 cookie 支持。

  • open(options)
  • EnvironBuilder 一样的参数还有一些补充: 你可以提供一个EnvironBuilder 类或一个 WSGI 环境代替 EnvironBuilder类作为参数。同时有两个可选参数 (as_tuple, buffered),可以改变返回值的类型或应用执行方法。

在 0.5 版更改: 如果为 data 参数提供一个带文件的字典,那么内容类型必须为 content_type而不是 mimetype。这个改变是为了和 werkzeug.FileWrapper 保持一致。

follow_redirects 参数被添加到 open().

Additional parameters:

参数:

  1. - **as_tuple** 在表格中返回一个元组 (environ,result)。
  2. - **buffered** 把这个设为 True 来缓冲区运行应用。这个将会为你自动关闭所有应用。
  3. - **follow_redirects** 如果接下来 _Client_ HTTP 重定向,这个将会设为 True
  • get(options)
  • 和 open 相似,但是方法强制执行 GET。

  • post(options)

  • 和 open 相似,但是方法强制执行 POST。

  • put(options)

  • 和 open 相似,但是方法强制执行 PUT。

  • delete(options)

  • 和 open 相似,但是方法强制执行 DELETE。

  • head(options)

  • 和 open 相似,但是方法强制执行 HEAD。
  • tests.createenviron([_options])
  • 根据传入的值创建一个 WSGI 环境。第一个参数应该是请求的路径,默认为 ‘/’。另一个参数或者是一个绝对路径(在这个例子中主机是 localhost:80)或请求的完整路径,端口和脚本路径。

它和 EnvironBuilder 构造函数接受相同的参数。

在 0.5 版更改: 这个函数现在是一个 EnvironBuilder 包裹,在 0.5 版本被添加。需要 headers, environ_base, environ_overridescharset 参数。

  • tests.runwsgi_app(_app, environ, buffered=False)
  • 返回一个应用输出的元组形式 (app_iter, status, headers)。如果你通过应用返回一个迭代器他将会工作的更好。

有时应用可以使用 start_ewsponse 返回的 write() 回调函数。这将会自动解决边界情况。如果没有得到预期输出,你应该将 buffered 设为 True 执行buffering

如果传入一个错误的应用,这个函数将会是未定义的。不要给这个函数传入一个不标准的 WSGI 应用。

参数:

  • app – 要执行的应用。
  • buffered – 设为 True 来执行 buffering.返回:元组形式 (app_iter,status,headers)