分离“;上下文”;以及“;触发器”;茉莉花

Separation of "context" and "trigger" in jasmine

本文关键字:触发器 茉莉花 上下文 分离 以及      更新时间:2024-05-29

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

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

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的一些功能。

这就是为什么描述块可以嵌套,并且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
      • 隐藏页面内容时执行的其他操作

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

虽然测试更像是一个矩阵(状态×特征),但大多数测试系统都给了我们一棵树。你是按状态还是按功能从树中分支,这在某种程度上取决于你,取决于哪个具有更高的复杂性。