基于示例的规格说明:DevOps 自动化测试的有效实践
1. 明确需求与定义验收标准
为了清晰地阐述需求,我们需要为每个需求确定一份验收标准列表。首先,列出一系列关键示例来阐释每个需求。以下是一些可能的示例:
- 作为买家,为了找到最划算的交易,我希望查看特定类别中的所有可用广告。
- 作为买家,为了更快找到感兴趣的物品,我希望能够列出描述或标题中包含特定关键词的所有广告。
- 列出“家居与园艺”类别中的所有广告。
- 列出“宠物与动物”类别中包含“小狗”一词的所有广告。
- 列出租金在 400 美元至 500 美元之间的所有房产。
- 列出新南威尔士州待售的所有房产。
这些具体示例有助于更清晰地呈现需求,同时也引发对需求细节和范围的讨论。例如,我们可能会发现,在特定类别广告中进行关键词搜索会更有用,“列出‘宠物与动物’类别中包含‘小狗’一词的所有广告”这个示例就体现了这一想法。
2. 细化示例
定义好验收标准后,我们将这些示例细化为更结构化的形式,以便在后续阶段更轻松地实现自动化。常用的方法是使用“给定 - 何时 - 那么”(given - when - then)结构来详细阐述示例,这种结构聚焦于操作和预期结果。以下是基于上述示例的细化:
Given Sally wants to buy a puppy for her son
When she looks for ads in the "Pets and Animals" category containing the word "puppy"
Then she should obtain a list of ads related to puppies.
或者
Given that Joe wants to rent an apartment in his budget
When he looks for "To Rent" ads in the "Property" category between $400 and $500
Then he should obtain a list containing only "To Rent" ads in this price range.
这些需求关注每个功能的业务价值,而不涉及功能实际实现或测试的细节,重点在于预期的业务结果,而非实现方式。
3. 自动化验收标准
正式确定验收标准后,我们可以将其自动化,即把验收标准实现为自动化测试,并作为自动化构建过程的一部分运行。首次运行测试时,由于相关功能尚未实现,测试自然会失败。
使用 Thucydides 时,通常会使用行为驱动开发(BDD)工具,如 easyb 或 JBehave。正如 Dan North 所说:“行为驱动开发(BDD)认为,只要需求足够明确,每个人都清楚要做什么,就能简单有效地将需求转化为已实现、经过测试且可投入生产的代码。BDD 以故事作为功能和交付的基本单位,验收标准是故事的内在组成部分。”虽然并非必不可少,但专业的 BDD 工具能让非开发人员更轻松自然地使用易于理解的语言和结构来表达自动化验收标准。
在 easyb 中,一个简单的自动化场景如下:
scenario "List all of the ads containing the word 'puppy' in the 'Pets and animals' category", {
given "Sally wants to buy a puppy for her son"
when "she looks for ads in the 'Pets and Animals' category containing the word 'puppy'"
then "she should see a list of ads related to puppies."
}
为了将这个故事集成到 Thucydides 中,我们需要添加更多细节,包括该验收标准所关联的功能,具体如下:
using "thucydides"
thucydides.tests.feature "Search ads"
scenario "List all of the ads containing the word 'puppy' in the 'Pets and animals' category", {
given "Sally wants to buy a puppy for her son"
when "she looks for ads in the 'Pets and Animals' category containing the word 'puppy'"
then "she should see a list of ads related to puppies."
}
同样,我们会详细阐述并自动化其他打算实现的验收标准,这通常在迭代或冲刺开始时进行,能清晰展示当前冲刺要实现的功能以及每个功能必须满足的验收标准。
在 Thucydides 中,验收标准通常会按任意分组组织,如功能、行为等,这有助于从更高层面了解项目进展和可交付内容。自动化后,验收标准从单纯的文本文档转变为可执行的规格说明,我们可以在自动化构建过程中运行它们,并生成类似图 10 - 2 的报告,该报告能提供验收标准状态的高级概述。这些报告还便于深入查看特定功能或功能区域,以了解其准备状态。
4. 编写测试的时机
测试编写的时机很重要。通常在编码开始时或之前编写测试效果最佳。团队在编写大量详细的可执行测试时,如果在代码编写之前就进行,或者等待太久才编写,都可能遇到问题。因此,团队需要通过实践找到合适的时机。
5. 实施测试
下一步是实现这些故事,使其真正执行预期的测试。由于我们测试的是 Web 应用程序,使用自动化 Web 测试来实现至少部分验收标准是合理的。随着 Web 应用程序设计变得更加复杂和交互性更强,实施这些测试变得越来越重要。
我们可以直接使用 Selenium 2 等 Web 测试库来实现上述故事,但这会导致自动化验收标准中出现大量低级细节,使自动化验收标准变得脆弱且难以维护。更好的做法是将这些细节与功能规格说明隔离开来。
编写高级测试后,我们将这些高级测试分解为细粒度的步骤。
6. 将高级测试分解为步骤
实施验收标准时,我们首先将其分解为逻辑步骤。这些步骤仍用高级业务术语表达,不包含过多实现细节,旨在说明用户如何实现相应的业务目标,而不过多涉及实现细节。这一步通常在迭代开始时或开始处理某个功能之前进行,由开发人员、测试人员和产品所有者或业务分析师共同完成。
以下是团队在 Thucydides 中对之前考虑的验收标准进行细化后的更详细场景,添加了对步骤类的引用和导入语句:
import com.acme.onlineclassifieds.webtests.steps.BuyerSteps
using "thucydides"
thucydides.tests.feature "Search ads"
thucydides.uses_default_base_url "http://my.staging.server"
thucydides.uses_steps_named("sally").from BuyerSteps
scenario "List all of the ads containing the word 'puppy' in the 'Pets and animals' category", {
given "Sally wants to buy a puppy for her son"
when "she looks for ads in the 'Pets and Animals' category containing the word 'puppy'", {
sally.opens_home_page()
sally.chooses_category "Pets & Animals"
sally.looks_for_ads_containing_keywords "puppy"
}
then "she should see a list of ads related to puppies.", {
sally.should_only_see_results_with_titles_containing "puppy"
}
}
这种方法有两个主要优点:一是验收测试的实现对非开发人员来说仍然具有很高的可读性,编写方式能让意图一目了然;二是这些步骤可作为构建块在其他测试中复用,使测试编写更快、维护更方便。
7. 表驱动测试
在某些情况下,可能需要几个略有不同的示例来阐释特定功能。例如,普通客户可以获得特殊的金卡,根据卡上积累的积分获得不同的折扣率。为了处理这类情况,大多数 BDD 工具支持使用表驱动测试。在 easyb 中,测试示例如下:
scenario "A Gold Card customer gets a discount based on the number of points gained from previous sales", {
given "Jill has a Gold Card with #numberOfPoints points"
when "she buys an article"
then "she should receive a #percentageDiscount discount"
where "examples of percentage discounts for different point values", {
numberOfPoints = [0, 50, 100, 200]
percentageDiscount = [0.0, 2.5, 5.0, 7.5]
}
}
表驱动测试是指定复杂场景的强大方法,但高级场景只是测试的一部分,我们还需要实现这些场景并将其映射到具体驱动 GUI 的步骤,这将在后续部分讨论。
8. 测试步骤作为 Java 或 Groovy 类
在所有情况下,Thucydides 步骤本身都在 Java 或 Groovy 类中实现为可复用的方法。它们最初可能只是简单的占位符,标记为“待处理”步骤,示例如下:
class BuyerSteps extends ScenarioSteps {
BuyerSteps(Pages pages) {
super(pages)
}
@Pending @Step
def opens_home_page() {}
@Pending @Step
def chooses_category(name) {}
@Pending @Step
def chooses_by_keywords(name, keywords) {}
// ...
}
Java 或 Groovy 类可以轻松集成到持续交付系统(如基于 Jenkins 的系统)中。
9. 将步骤转化为有效测试
完成上述步骤后,Thucydides 报告将显示所有场景步骤,为如何实现该功能提供实时文档。这有助于记录需求和实现方式,建议在每次构建时自动发布这些报告,并让所有团队成员都能轻松访问(例如,将其放在项目维基上),以确保产品所有者和测试人员对需要实现的内容有一致的理解。
当开发的功能变得更加稳定时,这些步骤可以充实并转化为有效的测试。这主要涉及实现步骤方法,使其真正对被测应用程序进行测试。
好的步骤实现通常相对简单,对于 Web 测试,通常会委托给 Selenium 2 页面对象类来与实际网页进行交互。编写步骤实现时,开发人员还应考虑在适当的时候重构现有步骤,使其在不同测试中更具可复用性。以下是一个用 Groovy 实现的简单步骤示例:
class BuyerSteps extends ScenarioSteps {
BuyerSteps(Pages pages) {
super(pages)
}
@Step
def opens_home_page() {
pages[HomePage].open()
}
@Step
def chooses_category(name) {
pages[HomePage].chooseCategory(name)
}
@Step
def chooses_by_keywords(name, keywords) {
pages[HomePage].searchByKeywords(keywords)
}
@Step
def should_only_see_results_with_prices_bewteen(int minimumPrice, int maximumPrice) {
def prices = pages[SearchResultsPage].getPrices()
prices.each {
assert (it >= minimumPrice && it <= maximumPrice)
}
}
// ...
}
10. 页面对象模式
这些步骤方法大量使用了页面对象模式。页面对象模式是一种与工具和框架无关的方法,它将网页的细节封装在一个类中,使用更具业务导向的方法名。例如,在上述步骤实现中,我们使用“chooseCategory”和“searchByKeyword”等术语,而不是直接引用 HTML 字段或按钮。这不仅使步骤实现更具可读性,还便于维护,因为对特定页面的更改只需在相应的页面对象中进行,而不是在使用该页面的每个测试中进行。简而言之,页面对象将测试与 GUI 交互的区域建模为测试代码中的对象,该模式有助于代码复用(减少重复代码,UI 更改时只需在一处修复)和维护(代码逻辑与页面分离)。
Selenium 2 和 Thucydides 都为页面对象模式提供了强大的支持,使网页交互的实际实现更易于编写和维护。以下是一个使用 Thucydides 的简单页面对象类示例:
class ClassifiedAdsPage extends PageObject {
WebElement search;
// ...
NewsClassifiedPage(WebDriver driver) {
super(driver)
}
def chooseCategory(name) {
findBy('.name').then(By.partialLinkText(name)).then().click()
}
def searchByKeywords(keywords) {
element(search).typeAndEnter(keywords)
}
// ...
}
11. 测试结果报告
随着项目的推进,故事将得到实现,验收测试将通过。通过的验收测试的相对数量能清晰展示已完成的工作量和剩余的工作量。了解验收标准自动化示例中涉及的步骤数量也很有用,通常,执行验收标准涉及的步骤越多,相应功能的实现就越复杂。因此,不仅报告通过和待处理测试的数量,还报告相应功能的相对复杂性(基于测试中涉及的步骤数量)是有益的,这能比仅依据通过测试的数量更全面地衡量项目进展。
能够深入查看特定功能的通过和待处理测试数量也很有价值。ATDD 报告的一个重要部分是既能看到整体情况,又能聚焦于特定功能,根据相应自动化验收标准的数量和质量评估其准备状态。
12. 提供实时文档
ATDD 技术还应提供一种实时文档,追溯业务目标和请求的功能,直至详细说明这些功能如何实现的叙述性示例。实时文档不仅有助于以所有项目成员都能理解的方式表达规格说明,还能确保这些规格说明始终是最新的。如果规格说明与系统的实际行为不匹配,相应的测试将失败。因此,这些实时规格说明成为系统预期功能的唯一真实来源,在对系统进行更改时也成为非常宝贵的资源。
已实现功能的报告既显示高级业务目标(以“给定 - 何时 - 那么”短语的形式),也显示说明如何实现该目标的步骤。不同的利益相关者(特别是开发人员和产品所有者)还可以浏览相应的截图,查看实现与运行中的应用程序的匹配情况。截图在测试失败时可用于调试,这不仅是实时文档的一部分,还能帮助业务所有者增强对自动化测试质量的信心。
13. 总结
DevOps 需要足够的自动化测试套件和对这些测试的高度信心才能实现。基于示例的规格说明提供了一种建立这种信心的方法,首先以高级业务术语表达需求,然后将这些需求自动化,提供一套实时文档,详细说明请求的需求和实现方式。随着项目的推进,这种实时文档将成为项目开发和维护的重要资产。
14. 测试流程总结
为了更清晰地呈现整个测试过程,我们可以用一个流程图来概括:
graph LR
A[明确需求与定义验收标准] --> B[细化示例]
B --> C[自动化验收标准]
C --> D{编写测试时机}
D -->|合适时机| E[实施测试]
E --> F[将高级测试分解为步骤]
F --> G[表驱动测试]
G --> H[测试步骤作为 Java 或 Groovy 类]
H --> I[将步骤转化为有效测试]
I --> J[页面对象模式]
J --> K[测试结果报告]
K --> L[提供实时文档]
从这个流程图可以看出,整个测试过程是一个循序渐进的过程,每个步骤都为后续步骤奠定基础。
15. 不同阶段的关键要点
15.1 需求与示例阶段
- 明确需求 :通过具体的示例来清晰地定义需求,确保所有相关人员对需求有一致的理解。例如,列出不同场景下的搜索需求,如特定类别、特定关键词等。
- 细化示例 :使用“给定 - 何时 - 那么”结构将示例转化为可操作的测试场景,聚焦业务价值。
15.2 自动化与测试阶段
- 自动化验收标准 :选择合适的 BDD 工具(如 easyb 或 JBehave)将验收标准自动化,使其成为可执行的规格说明。
- 测试编写时机 :找到合适的测试编写时机,避免过早或过晚编写测试带来的问题。
- 实施测试 :采用自动化 Web 测试实现部分验收标准,注意将低级细节与功能规格说明分离。
- 分解测试步骤 :将高级测试分解为逻辑步骤,用高级业务术语表达,便于非开发人员理解和复用。
15.3 代码实现与模式阶段
- 表驱动测试 :对于复杂场景,使用表驱动测试来处理不同的示例情况。
- 测试步骤类 :将 Thucydides 步骤在 Java 或 Groovy 类中实现为可复用的方法,便于集成到持续交付系统。
- 页面对象模式 :使用页面对象模式封装网页细节,提高代码的可读性和可维护性。
15.4 报告与文档阶段
- 测试结果报告 :报告不仅要显示通过和待处理测试的数量,还要体现功能的相对复杂性,以便全面评估项目进展。
- 实时文档 :提供实时文档,确保规格说明与系统实际行为一致,增强利益相关者对测试的信心。
16. 实际应用中的注意事项
16.1 团队协作
在整个测试过程中,团队协作至关重要。开发人员、测试人员和产品所有者或业务分析师需要密切合作,特别是在将高级测试分解为步骤和编写测试步骤类时。例如,在 Thucydides 中细化验收标准的场景时,需要各方共同参与,确保步骤既能满足业务需求,又具有可实现性。
16.2 代码维护
随着项目的推进,代码的维护变得尤为重要。使用页面对象模式可以减少代码的重复,提高代码的可维护性。但开发人员还需要定期对代码进行重构,特别是在测试步骤类中,确保步骤方法在不同测试中更具可复用性。
16.3 测试覆盖度
为了确保系统的质量,需要保证测试的覆盖度。在编写测试时,要考虑各种可能的场景,包括正常情况和异常情况。例如,在表驱动测试中,要涵盖不同的输入值,以确保系统在各种情况下都能正常工作。
17. 总结与展望
基于示例的规格说明为 DevOps 中的自动化测试提供了一种有效的方法。通过明确需求、自动化验收标准、实施测试等一系列步骤,我们可以建立起一套可靠的测试体系,同时提供实时文档,确保项目的顺利进行。
在未来的项目中,我们可以进一步优化这个测试流程。例如,结合更多的自动化工具和技术,提高测试的效率和准确性。同时,加强团队成员的培训,提高他们对基于示例的规格说明和相关测试技术的理解和应用能力。
总之,基于示例的规格说明是 DevOps 中自动化测试的重要实践,值得我们在实际项目中不断探索和应用。通过不断地优化和改进,我们可以更好地满足业务需求,提高系统的质量和稳定性。
18. 示例对比总结
为了更直观地展示不同阶段的特点,我们可以用一个表格进行总结:
| 阶段 | 主要任务 | 关键技术 | 优点 |
| ---- | ---- | ---- | ---- |
| 需求与示例 | 明确需求,列出示例 | “给定 - 何时 - 那么”结构 | 清晰表达需求,聚焦业务价值 |
| 自动化与测试 | 自动化验收标准,编写测试 | BDD 工具,自动化 Web 测试 | 可执行的规格说明,提高测试效率 |
| 代码实现与模式 | 实现测试步骤,使用页面对象模式 | Java 或 Groovy 类,页面对象模式 | 代码复用,易于维护 |
| 报告与文档 | 报告测试结果,提供实时文档 | 测试结果报告,实时文档 | 全面评估项目,确保规格说明准确 |
通过这个表格,我们可以更清晰地看到每个阶段的重点和优势,有助于在实际项目中更好地应用这些技术和方法。
超级会员免费看
1210

被折叠的 条评论
为什么被折叠?



