定义构建CoreJet测试的测试基础设施
项目描述
CoreJet
CoreJet是一种行为驱动测试规范和方法,Python和Java都有实现。有关详细信息,请参阅http://corejet.org。
此软件包在Python中提供了CoreJet的核心功能。您可能还会对corejet.testrunner感兴趣,可能还会对corejet.jira感兴趣。
为什么不选择Cucumber?
有各种软件包在Python中实现了类似的BDD测试风格,通常基于Cucumber。CoreJet有一个重要的哲学差异:不是在纯文本文件中编写故事和场景,而是打算将它们作为需求管理系统的组成部分进行管理,例如JIRA(因此有corejet.jira)。这管理史诗、故事和场景,以及与需求相关的生命周期和元数据:它们是打开还是关闭,有多大(在故事点中),以及它们对业务用户的价值(优先级)。
“需求目录源”将从该系统提取需求,以中间XML格式(见下文)或直接进入CoreJet数据模型(同样,见下文)。测试运行器(corejet.testrunner)首先获取当前需求目录,然后执行所有CoreJet测试,匹配故事(通过id)和场景(通过名称),并将每个测试的状态设置为“通过”、“失败”、“待定”(尚未实现)或“不匹配”(场景中的给定/当/然后步骤与需求管理系统不同步)。
此分析的结果将写入增强的CoreJet XML文件。然后,它用于生成项目状态的视觉表示(见corejet.visualization),并使用颜色编码来指示项目完成程度,其中“完成”表示有通过自动测试且准确反映业务验收标准。
安装
您可以将corejet.core作为您包的依赖项安装,例如在setup.py中添加
install_requires=['corejet.core']
或者,如果您更喜欢将测试保留在额外的
extras_require = {'test': ['corejet.core']}
但是请注意,corejet.core依赖于lxml库。在OS X和较老的Linux平台上安装它有时有点棘手。如果您使用Buildout安装包,您可能想要使用z3c.recipe.lxml来安装lxml:将lxml作为您的parts列表中的第一个项目,然后添加此部分
[lxml] recipe = z3c.recipe.staticlxml egg = lxml
测试语法
要在Python中编写CoreJet测试,您可以使用此包中找到的装饰器与unittest风格测试用例结合使用。为此,您应该在您的包(或在至少测试依赖列表中)依赖corejet.core,如果使用Python 2.6或更早版本,可能还需要unittest2。
以下是一个示例
import unittest2 as unittest from corejet.core import Scenario, story, scenario, given, when, then @story(id="S1", title="As a user, I can log in") class Login(unittest.TestCase): @scenario("Invalid username") class InvalidUsername(Scenario): @given("A user 'joebloggs' with password 'secret'") def setupUser(self): # Some precondition logic, e.g. createUser('jobloggs', 'secret') @when("Entering the username 'jobloggs' and password 'secret'") def attemptLogin(self): # Call some action logic, e.g. loginAs('jobloggs', 'secret') @then("An error is shown") def checkOutput(self): # Perform some assertion, e.g. errorMessages = getErrorMessages() self.assertTrue("Invalid username" in errorMessages) @scenario("Invalid password") class InvalidPassword(Scenario): @given("A user 'joebloggs' with password 'secret'") def setupUser(self): # Some precondition logic, e.g. createUser('jobloggs', 'secret') @when("Entering the username 'joebloggs' and password 'uhoh'") def attemptLogin(self): # Call some action logic, e.g. loginAs('joebloggs', 'uhph') @then("An error is shown") def checkOutput(self): # Perform some assertion, e.g. errorMessages = getErrorMessages() self.assertTrue("Invalid password" in errorMessages)
您可以拥有任意多或任意少的场景。Scenario基类提供了一个属性self.story,这是一个外部的@story注解的测试用例类的实例。这允许访问共享属性或状态。您还可以在外部类(但不是在Scenario类)上使用标准的unittest约定,如setUp()和tearDown()来管理您的测试设置。
实际上,在运行时,每个内部场景类都会被转换成外部故事类的一个标准方法,其名称为test_<ScenarioName>(),当调用时,将调用内部类中的每个@given注解的方法,然后调用每个@when注解的方法,最后调用每个@then注解的方法。
这样做的原因是为了确保标准测试收集器能够正常工作。实际上,CoreJet测试应该与任何可以执行unittest测试的标准测试运行器一起工作。
当然,使用CoreJet的主要原因是生成完成的函数覆盖率报告。为此,您可以使用corejet.testrunner中的测试运行器与需求目录源结合使用。请参阅该包的详细信息。
数据模型
标准CoreJet数据模型在本包中以模块 corejet.core.model 的形式表示,并由 corejet.core.interfaces 中的接口进行描述。其主要类是 RequirementsCatalogue,其中包含一个 Epic 对象列表,每个 Epic 对象又包含一个 Story 对象列表,每个 Story 对象又包含一个 Scenario 对象列表,每个 Scenario 对象又包含三个 Step 对象的列表(给定、当、然后)。
有关更多详细信息,请参阅源代码中的文档。
XML解析和序列化
RequirementsCatalog 类提供了 populate() 和 write() 方法,分别用于读取和写入标准 CoreJet XML 文件以初始化或序列化目录。
以下是一个示例文件,其中包含一个故事和两个场景,这些场景包含在一个虚构的史诗中
<requirementscatalogue project="Acme Corp" extractTime="2011-05-15T19:00:00"> <epic id="E1" title="User management"> <story id="S1" title="As a user, I can log in" requirementStatus="closed" resolution="fixed" priority="high"> <scenario name="Invalid username"> <given>A user 'joebloggs' with password 'secret'</given> <when>Entering the username 'jobloggs' and password 'secret'</when> <then>An error is shown</then> </scenario> <scenario name="Invalid password"> <given>A user 'joebloggs' with password 'secret'</given> <when>Entering the username 'joebloggs' and password 'uhoh'</when> <then>An error is shown</then> </scenario> </story> </epic> </requirementscatalogue>
场景解析器
场景通常使用“Gherkin”语法编写(类似于 Cucumber 框架,CoreJet 部分受其启发)。
场景可以像这样以纯文本形式编写
Scenario: Invalid username Given A user 'joebloggs' with password 'secret' When Entering the username 'jobloggs' and password 'secret' Then An error is shown Scenario: Invalid password Given A user 'joebloggs' with password 'secret' When Entering the username 'joebloggs' and password 'uhoh' Then An error is shown Scenario: Cancel button Given A user 'joebloggs' with password 'secret' When Entering the username 'joebloggs' and password 'uhoh' And Clicking the 'cancel' button Then The user is taken away from the page And A warning is shown
场景之前可以有一个背景描述,该描述由一个或多个影响每个场景的“给定”子句组成
Given I'm logged in And I've got superuser privileges Scenario: ...
此外,还支持基本的“场景概述”和“示例”。
完整的 Gherkin 语法更复杂,但要解析这种简化的场景样式并将其附加到故事中,可以使用 corejet.core.parser.appendScenarios 函数。它接受一个 Story 和一个包含验收标准文本的字符串作为其两个参数。
解析器相对宽容,但请注意
解析器不区分大小写
可能存在零个或多个场景
场景必须以“场景:”开头,后面跟一个名称
“给定”子句是可选的,但在场景中必须首先出现
“当”子句是必需的,并且必须位于“然后”子句之前
“然后”子句也是必需的
“和”或“但”子句可以跟在“给定”、“当”或“然后”之后,但不能是第一个。
生成测试骨架
corejet.core 包含一个用于为 Python unittest 生成测试骨架的 XSLT 样式表。如果您使用 buildout,可以使用以下命令安装辅助脚本以执行 XSLT 转换
[corejet2py] recipe = zc.recipe.rgg eggs = corejet.core scripts = corejet2py
并执行它
bin/corejet2py path/to/corejet.xml
尝试 bin/corejet2py --help 以获取更多信息。
变更日志
1.1.0 (2016-08-26)
修复了与 python-dateutil >= 2.0devw 兼容的问题 [datakurre]
1.0.2 (2012-05-30)
修复了测试骨架生成 XSLT 以删除额外空格的问题 [datakurre]
1.0.1 (2012-05-27)
添加了从测试报告中生成测试骨架的辅助脚本。将‘argparse’添加到需求中 [datakurre]
1.0.0
添加了芬兰语支持(‘# language: fi’) [datakurre]
添加了对类似 Cucumber 的‘language’关键字的解析器支持 [datakurre]
添加了对“场景概述”和“示例”的解析器支持 [datakurre]
添加了新的步骤关键字 but 作为 and 的别名 [datakurre]
修改了装饰器,通过标准化各自的标题来命名测试模块和方法 [datakurre]
完成了对故事级别步骤的支持 [datakurre]
确保引号(”)转换为撇号(‘) [datakurre]
修复了 corejet-to-python.xsl 以生成可运行的测试骨架 [datakurre]
1.0a4
确保同一类型的多个步骤始终按正确的顺序执行。 [optilude]
1.0a3
修复了损坏的包 [optilude]
1.0a1
首次发布 [optilude]
项目详细信息
corejet.core-1.1.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 70c1a92912dcb0fd8b5746748c070173f87ef9bd9b4f65204a53e12f66db44e9 |
|
MD5 | 76c69debed40700495fbd9e95fc1028a |
|
BLAKE2b-256 | 3312702eaef0d1a883e2d321ab1c76d6e0d7d344c81f9c06246abc4e8b888080 |