假设我有一个简单的页面,点击页面标题可以切换页面内容的可见性(现实?不,但这是一个包含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();
});
});
});
});
如何从上下文中分离触发器(在这种情况下引发'click')(shared =加载fixture,具体=隐藏页面内容)避免代码重复?
如果有帮助,这就是我在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的一些功能,以保持示例简单。
答案 0 :(得分:4)
这就是为什么描述块可以嵌套的原因,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();
});
});
});
});
或者,如果必须,在该描述块中设置辅助宏函数,但这可能会变得很难看。它开始在你的测试中放入过多的逻辑。最终你需要测试你的测试。哟dawg ......
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
此结构允许您根据初始状态进行钻取,因此如果您有更多依赖于页面可见性的功能,则可以轻松测试这些功能,因为您已经拥有了具有该状态设置的位置,您可以在其中删除新的测试。
虽然测试可能更像矩阵(状态×特征),但大多数测试系统给我们一棵树。是否按状态或功能从该树分支取决于您的具体程度,具体取决于哪个具有更高的复杂度。