测试关注点分离
测试关注点分离是 关注点分离 的一种形式,其中测试的用户故事是声明式描述的,并且与执行它的 图灵完备 代码(“引擎”)完全分开。
它反映了遵循 MVC 模式(在 Django 世界中为 MTV)的 Web 应用程序所表现出的关注点分离。使用 hitchstory,一个非图灵完备、声明式用户故事的示例看起来像这样
Logged in as AzureDiamond:
given:
browser: firefox
steps:
- Visit: /login
- Form filled:
username: AzureDiamond
password: hunter2
- Click: login
- Page should appear: dashboard
相应的引擎代码看起来像这样
def form_filled(self, **textboxes):
for name, contents in sorted(textboxes.items()):
self.driver.fill_form(name, contents)
def click(self, name):
self.driver.click(name=name)
xUnit 测试:没有关注点分离
与 hitchstory 不同,xUnit 测试没有层来强制分离测试关注点。
尽管如此,熟练的开发人员通常可以从代码中阅读和推导出预期的用户故事,尤其是在代码编写清晰且有良好注释的情况下。例如,与上述等效项可能是
def test_add_user(browser, web_server, init, dbsession):
"""Log in as AzureDiamond"""
b = browser
b.visit("https://127.0.0.1:8080/")
b.find_by_css("#nav-admin").click()
b.find_by_css("#btn-panel-login").click()
b.fill("email", "AzureDiamond")
b.fill("password", "hunter2")
b.find_by_name("login").click()
assert b.is_element_present_by_css("#nav-dash")
然而,情况并非总是如此,而且经常出现的情况是,即使对于熟练的开发人员来说,也难以从测试中推导出预期的行为。
没有分离:可读性较差
并非所有测试都有容易辨别的规范。例如
def test_edit_article_url_is_resolved(self):
url = reverse('mumbles-api-articles:edit-article',args=['sOmE-iD'])
self.assertEquals(resolve(url).func,edit_article)
这不是测试编写者的问题 - 而是 xUnit 测试的固有问题。随着它们的发展,它们变得越来越难以阅读,而且由于它们主要与代码 API 交互,因此与整体应用程序的相关性可能难以辨别。
Cucumber / Gherkin:仅在高级描述和其余部分之间进行分离
Cucumber(以及它的衍生产品)是另一个强制使用语言层的框架,但它没有强制在规范和执行之间进行分离,而是围绕创建更有用的分离(在高级规范和其余部分之间)进行塑造。
这种高级场景的一个示例(来自具有代表性的 cucumber 教程)是
Scenario: Create a new person
Given API: I create a new person
Then API: I check that POST call body is "OK"
And API: I check that POST call status code is 200
此示例展示了 测试关注点泄漏。
这提供了一个有限的窗口,了解 API 的预期(或实际)行为,因为它只是对 API 行为的非常高级别的概述。有关此故事的关键规范详细信息仍将存在于此可执行规范中,但它们将被埋藏在上述内容所转换为的步骤代码中。
由于需要隐藏关键规范细节(例如,创建人员的API调用的内容),步骤代码也必须高度专业化,从而抑制步骤代码的可重用性。