跳至内容

测试关注点分离

测试关注点分离是 关注点分离 的一种形式,其中测试的用户故事是声明式描述的,并且与执行它的 图灵完备 代码(“引擎”)完全分开。

它反映了遵循 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调用的内容),步骤代码也必须高度专业化,从而抑制步骤代码的可重用性。