3

假设我有一个简单的页面,通过单击页面标题来切换页面内容的可见性(现实吗?不,但这是一个包含 DOM 元素的简单测试)。我会为您省去 HTML 和 JS 实现,因为我相信您会在脑海中看到它。

我正在尝试使用 jasmine 对此进行测试,但遇到了代码重复问题,主要是围绕上下文的分离(此测试与它的兄弟不同)和触发器(正在测试的操作和捕获结果)

describe("Home", function () {
    describe("Selecting the page title", function () {
        beforeEach(function () {
            loadFixtures('Home.fixture.htm');
        });

        describe("when page content is visible", function () {
            it("should hide page content", function () {
                $('#pageTitle').trigger('click');

                expect($('#pageContent')).toBeHidden();
            });
        });

        describe("when page content is hidden", function () {
            it("should show page content", function () {
                $('#pageContent').hide();
                $('#pageTitle').trigger('click');

                expect($('#pageContent')).toBeVisible();
            });
        });
    });
});

如何将触发器(在这种情况下引发“点击”)与上下文(共享 = 加载夹具,特定 = 隐藏页面内容)分开以避免代码重复?

如果有帮助,这就是我在 MSpec(.NET 的上下文/规范框架)中要做的事情:

[Subject("Home")]
class when_selecting_the_page_title_when_page_content_is_visible : HomeContext
{
    It should_hide_page_content = () =>
        // Assert that page content is hidden
}

[Subject("Home")]
class when_selecting_the_page_title_when_page_content_is_hidden : HomeContext
{
    Establish context = () =>
        // Hide page content

    It should_show_page_content = () =>
        // Assert that page content is visible
}

class HomeContext
{
    Establish context = () =>
        // Load the fixture

    Because of = () =>
        // Fire the event
}

免责声明:我不想在这里争论 C# 与 Javascript 或 MSpec 与任何东西,这只是为了提供我所追求的代码重用示例。我还跳过了 MSpec 的一些功能以保持示例简单。

4

1 回答 1

4

这就是为什么 describe 块可以嵌套,并且beforeEach()可以在仅适用于该级别及以下的任何级别调用。

我不会太担心测试中的代码重复。更多的间接意味着更少的可读性。在合理的范围内,测试中的冗长通常是一件好事。太多特定的宏函数只适用于你的代码的一小部分,你最终会得到一个巨大的脆弱测试球,很少有人能弄清楚如何改变。

describe("Home", function () {
    describe("Selecting the page title", function () {
        beforeEach(function () {
            loadFixtures('Home.fixture.htm');
        });

        describe("when page content is visible", function () {
            beforeEach(function() {
                $('#pageTitle').trigger('click');
            });

            it("should hide page content", function () {
                expect($('#pageContent')).toBeHidden();
            });
        });

        describe("when page content is hidden", function () {
            beforeEach(function() {
                $('#pageContent').hide();
                $('#pageTitle').trigger('click');
            });

            it("should show page content", function () {
                expect($('#pageContent')).toBeVisible();
            });
        });
    });
});

或者,如果必须,在该描述块中设置一个辅助宏函数,但这会很快变得丑陋。它开始在你的测试中加入太多的逻辑。最终,您需要为您的测试进行测试。哟呸...

describe("Home", function () {
    describe("Selecting the page title", function () {
        beforeEach(function () {
            this.loadHomeFixture = function(options) {
                options = options || {};
                loadFixtures('Home.fixture.htm');
                if (options.hidden) {
                    $('#pageContent').hide();
                }
            };
        });

        describe("when page content is visible", function () {
            it("should hide page content", function () {
                this.loadHomeFixture({ hidden: false });
                expect($('#pageContent')).toBeHidden();
            });
        });

        describe("when page content is hidden", function () {
            it("should show page content", function () {
                this.loadHomeFixture({ hidden: true });
                expect($('#pageContent')).toBeVisible();
            });
        });
    });
});

此外,有时我会先按状态组织测试,然后再按特征组织测试。允许您更清晰地将初始状态与操作分开。

以下是您可以如何以大纲形式执行此操作。

    • beforeEach: load home fixture
    • 当页面内容可见时
      • beforeEach: make content visible
      • 选择页面标题
        • beforeEach: click page title
        • 应该隐藏页面内容
          • assert page content is hidden
      • 当页面内容可见时执行某些操作的其他操作
    • 当页面内容被隐藏时
      • beforeEach: make content hidden
      • 选择页面标题
        • beforeEach: click page title
        • 应该显示页面内容
          • assert page content is visible
      • 隐藏页面内容时执行的其他操作

这种结构允许您根据初始状态进行深入研究,因此如果您有更多依赖于页面可见性的功能,则很容易测试这些功能,因为您已经有一个具有该状态设置的位置,您可以在其中删除新测试。

虽然测试可能更像是一个矩阵(状态 × 特征),但大多数测试系统给了我们一棵树。是否按状态或功能从该树分支取决于您,并且取决于哪个具有更高的复杂性。

于 2012-08-01T00:30:35.323 回答