测试

Pycsw使用 pytest 管理它的自动化测试。有许多测试套件主要执行功能测试。这些测试确保pycsw符合各种受支持的标准。还有一组不断增长的单元测试。这些测试集中在较小的范围内,以便验证各个代码位是否按预期工作.

测试可以作为开发周期的一部分在本地运行。它们还运行在pycsw的 Travis continuous integration服务器上,用于处理所有对代码存储库的推拉请求.

OGC引用

除了pycsw自己的测试,所有的公共版本也通过OGC的 Compliance & Interoperability Testing & Evaluation Initiative (CITE)进行测试。pycsw wiki 文档CITE 引用了测试过程和状态.

功能测试套件

目前大多数pycsw的测试都是 functional tests 。这意味着每个测试用例都基于pycsw实现的各种标准的规范所规定的需求。这些测试的重点是确保 pycsw按预期的那样工作.

每个测试遵循相同的工作流程:

  • 为每个测试套件创建一个新的pycsw实例,该实例具有自定义配置和数据存储库;
  • 对运行的pycsw 实例执行一系列GET和POST请求;
  • 将每个请求的结果与预先准备的预期结果进行比较。如果测试结果与预期结果一致,则测试通过,否则失败.

tests/functionaltests/suites 下存在许多不同的测试套件。每个套件指定以下结构:

  • 必须由测试套件使用的具有pycsw配置的强制 default.cfg ;

  • 包含每个请求的预期结果的强制性 expected/ 目录;

  • 一个可选的 data/ 目录,包含 .xml 文件,其中包含要在运行测试之前加载到套件数据库中的测试数据。该目录及其内容的存在对测试具有以下意义:

    • 如果 data/ 目录存在并且包含文件,它们将被加载到一个新的数据库中,用于运行套件的测试;
    • 如果存在 data/ 目录并且不包含任何数据文件,则在测试中使用新的空数据库;
    • 如果 data/ 目录不存在,套件将使用填充有 CITE 套件的测试数据的数据库.
  • 一个可选的 get/requests.txt 文件,其中保存用于生成HTTP GET请求的请求参数.

    文件中的每一行必须用以下方案格式化:

    test_id,request_query_string

    例如:

    TestGetCapabilities,service=CSW&version=2.0.2&request=GetCapabilities

    当测试运行时, test_id 用于命名每个测试并寻找预期结果.

  • 一个可选的 post/ 目录,它包含用于制作HTTP POST请求的 .xml 文件

测试标识符

每个测试都有一个标识符,该标识符是使用以下规则构建的:

<test_function>[<suite_name>_<http_method>_<test_name>]

例如:

test_suites[default_post_GetRecords-end]

Functional tests' implementation

tests/functionaltests/suites 下出现的每个套件目录生成功能测试。测试生成使用pytest's pytest_generate_tests 功能。这个功能在 tests/functionaltests/conftest.py 中实现。它提供了 tests/functionaltests/test_suites_functional:test_suites 功能的自动参数化。此参数化导致为套件目录中定义的每个 GET 和 POST 请求生成测试.

添加新测试

在现有套件中添加测试:

  • 对于HTTP POST测试,在 tests/functionaltests/suites/<suite>/post 添加XML文档
  • 对于HTTP GET测试,在 tests/functionaltests/suites/<suite>/get/requests.txt 中添加测试(每行的第一项)

添加新的测试套件:

  • tests/functionaltests/suites (如 foo )下创建一个新目录
  • tests/suites/foo/default.cfg 创建一个新的配置
  • tests/suites/foo/post 填写HTTP POST请求
  • tests/suites/foo/get/requests.txt 填写HTTP GET请求
  • 如果需要测试组件的测试数据,创建 tests/suites/foo/data,以存储XML文件。这会在运行时插入到测试目录
  • 使用如上所述的pytest或者 tox来运行测试

新的测试套件数据库将自动创建,并且会成为测试的一部分。

单元测试

pycsw还具有单元测试。这些用于处理测试单个功能的预期行为.

单元测试的通常实现是导入被测试的功能/方法,用一组已知的参数运行它,并断言结果与预期结果匹配.

Unit tests are defined in pycsw/tests/unittests/<module_name>.

pycsw的单元测试用 unit 来标记。这使得它们很容易单独运行:

# running only the unit tests (not the functional ones)
py.test -m unit

运行测试

由于pycsw使用 pytest,所以测试是用 py.test runner运行的。一个基本的测试运行可以用:

py.test

这个命令将运行所有测试,并报告成功、失败次数以及运行它们所花费的时间。 py.test 命令接受几个额外的参数,这些参数可用于自定义测试的执行。查看 pytest's invocation documentation,以获得更完整的描述。您还可以通过运行来获得可用参数的描述:

py.test --help

运行特定套件和测试用例

py.test 允许标记测试。这些可以用来选择性地运行一些测试。 pycsw 使用两个标记:

  • unit - 只运行inut测试
  • functional- 只运行功能测试

标记可以通过使用 -m <marker_name> 标志来指定.

py.test -m functional  # run only functional tests

您还可以使用 -k <name_expression> 标志来选择要运行哪些测试。由于每个测试的名称都包含套件名称、http方法和测试的标识符,因此仅运行某些测试很容易.

py.test -k "apiso and GetRecords"  # run only tests from the apiso suite that have GetRecords in their name
py.test -k "post and GetRecords"  # run only tests that use HTTP POST and GetRecords in their name
py.test -k "not harvesting"  # run all tests except those from the harvesting suite

-m and -k 标志可以组合起来.

快速退出

--exitfirst (or -x ) 标志可用于在测试用例失败时立即停止测试运行程序.

py.test --exitfirst

看到更多的输出

从运行测试中获得更多输出的主要方法有三种:

  • --verbose (or -v ) 标志;
  • 测试发送到stdout的 --capture=no flag - Messages不会被抑制;
  • --pycsw-loglevel 标志 - 设置被测试的pycsw实例的日志级别。将此值设置为 debug ,以便查看pycsw在处理请求时发送的所有调试消息.
py.test --verbose
py.test --pycsw-loglevel=debug
py.test -v --capture=no --pycsw-loglevel=debug

将结果与difflib而不是XML c14n进行比较

功能测试使用 [XML canonicalisation - XML c14n](https://www.w3.org/TR/xml-c14n/) 将结果与期望值进行比较。或者,也可以调用py, 使用 --functional-prefer-diffs 标志进行测试。这将支持基于 Python's difflib 的比较。在逐行比较的基础上,如果失败,将把统一的差异打印到标准输出.

py.test -m functional -k 'harvesting' --functional-prefer-diffs

在磁盘中保存测试结果

通过使用 --functional-save-results-directory 选项,可以将每个功能测试的结果保存到磁盘上。每个结果文件都是根据使用pytest运行时的测试标识符命名的.

py.test -m functional -k 'not harvesting' --functional-save-results-directory=/tmp/pycsw-test-results

测试覆盖率

使用 --cov pycsw 标志来查看代码覆盖率的信息。可以以各种格式获得输出.

py.test --cov pycsw

指定测试超时

--timeout <seconds> 选项可用于指定如果测试运行时间超过 <seconds>,则认为它已经失败。秒可以是一个浮点,所以可以指定次秒超时

py.test --timeout=1.5

Linting with flake8

使用 --flake8 标志也检查代码是否符合Python风格指南

py.test --flake8

测试多个Python版本

为了同时测试多个Python版本和配置,可以使用 tox 。 pycsw包含一个具有适当配置的 tox.ini 文件它可以用于对多个Python版本和多个数据库后端进行测试。在运行 tox 时,可以通过调用 tox <tox arguments> -- <py.test arguments>py.test 运行程序发送参数。例如:

# install tox on your system
sudo pip install tox

# run all tests on multiple Python versions against all databases,
# with default arguments
tox

# run tests only with python2.7 and using sqlite as backend
tox -e py27-sqlite

# run only csw30 suite tests with python3.5 and postgresql as backend
tox -e py35-postgresql -- -k 'csw30'

Web测试

您还可以通过Web浏览器使用pycsw测试,来执行你的pycsw安装样例申请。这些测试在 tests/ 中。生成HTML页面:

$ paver gen_tests_html

然后导航到 http://host/path/to/pycsw/tests/index.html