aurelia 测试的不确定性单元测试问题
Underterministic unit-test issues with aurelia-testing
此问题与 有关。我正在简要地重复一些细节。我想对我的 aurelia 自定义元素进行单元测试,如下所示。
// BaseText.ts
import { bindable } from "aurelia-framework";
import { BaseI18N } from "aurelia-i18n";
export class BaseText extends BaseI18N {
@bindable public value: string;
@bindable public i18nKey: string;
}
// NormalText.html; NormalText inherits from BaseText
<template>
<span t.bind="i18nKey">${value}</span>
</template>
// ValueText.html; ValueText inherits from BaseText
<template>
<strong t.bind="i18nKey">${value}</strong>
</template>
现在,我想测试这些自定义元素的视图,它们具有以下形式。
describe("View specs", () => {
it("Should render the text in a strong element without any additional style", (done) => {
const randomId = randomIdGenerator();
const component = StageComponent
.withResources("ValueText/ValueText")
.inView(`<value-text id='${randomId}' value='Hello Static Text'></value-text>`);
component
.create(bootstrap)
.then(() => {
const strongElement: HTMLElement = document.querySelector(`value-text#${randomId}>strong`);
console.log(strongElement);
expect(strongElement).toBeDefined();
expect(strongElement.style.cssText).toBeFalsy();
expect(Array.from(strongElement.classList).filter(item => !item.startsWith("au-")).length).toBe(0);
})
.catch(e => { console.log(e.toString()) })
.finally(() => {
component.dispose();
done();
});
});
it("Should render a dynamic text", (done) => {
const randomId = randomIdGenerator();
const component1 = StageComponent
.withResources("ValueText/ValueText")
.inView(`<value-text id='${randomId}' value.bind='boundValue'></value-text>`)
.boundTo({ boundValue: "Hello Value Text" });
component1
.create(bootstrap)
.then(() => {
const strongElement = document.querySelector(`value-text#${randomId}>strong`);
expect(strongElement.textContent.trim()).toBe('Hello Value Text');
})
.catch(e => { console.log(e.toString()) })
.finally(() => {
component1.dispose();
done();
});
});
it("Should render the provided static text without i18nKey", (done) => {
const randomId = randomIdGenerator();
const component2 = StageComponent
.withResources("ValueText/ValueText")
.inView(`<value-text id='${randomId}' value='Hello Static Text'></value-text>`);
component2
.create(bootstrap)
.then(() => {
const strongElement = document.querySelector(`value-text#${randomId}>strong`);
expect(strongElement.textContent.trim()).toBe('Hello Static Text');
})
.catch(e => { console.log(e.toString()) })
.finally(() => {
component2.dispose();
done();
});
});
});
虽然我在这里展示了 ValueText
的测试,但 NormalText
的测试看起来也非常相似。
当我 运行 分别针对这两个元素进行测试时,所有测试 运行 都很好。但是,当它们一起 运行 时,对于某些测试用例,document.querySelector('...')
会返回 undefined
元素。这导致 运行 没有 expect
断言。这导致了以下错误。
Spec 'HERE_GOES_SPEC_NAME' has no expectations.
经过一些调试,似乎当测试 运行 在一起时,对于第二个 运行 的测试套件,甚至没有创建自定义元素的视图。它创建一个 DOM 元素,如下所示。
<normal-text value="Hello Static Text"></normal-text>
但是缺少视图的 innerHTML 部分。更正式地说,在这些测试期间,关联的 viewmodel/controller 在 aurelia-templating 中仍然缺失,这导致了格式错误的视图。
我应该改变什么,使这些测试用例变得确定?
附加信息: 我创建了一个 GitHub repo,以便有兴趣的 reader/user 可以重现该问题。请记住,您可能 运行 多次测试以重现问题。
经过长时间的调试,事实证明,对于失败的测试规范(即 运行 秒后的测试套件),元数据是不正确的。例如,如果 NormalText
的测试套件首先是 运行,那么对于 ValueText
的测试套件,ValueText
的元数据反映了 NormalText
的元数据;更具体地说,NormalText
.
的 HTML(查看)资源
可能某处有错误或我编写测试的方式有问题。
但是,我找到了一个简单的解决方法,即在两个 类 上应用 @customElement("element-name")
装饰器。这确实解决了问题。
此问题与
// BaseText.ts
import { bindable } from "aurelia-framework";
import { BaseI18N } from "aurelia-i18n";
export class BaseText extends BaseI18N {
@bindable public value: string;
@bindable public i18nKey: string;
}
// NormalText.html; NormalText inherits from BaseText
<template>
<span t.bind="i18nKey">${value}</span>
</template>
// ValueText.html; ValueText inherits from BaseText
<template>
<strong t.bind="i18nKey">${value}</strong>
</template>
现在,我想测试这些自定义元素的视图,它们具有以下形式。
describe("View specs", () => {
it("Should render the text in a strong element without any additional style", (done) => {
const randomId = randomIdGenerator();
const component = StageComponent
.withResources("ValueText/ValueText")
.inView(`<value-text id='${randomId}' value='Hello Static Text'></value-text>`);
component
.create(bootstrap)
.then(() => {
const strongElement: HTMLElement = document.querySelector(`value-text#${randomId}>strong`);
console.log(strongElement);
expect(strongElement).toBeDefined();
expect(strongElement.style.cssText).toBeFalsy();
expect(Array.from(strongElement.classList).filter(item => !item.startsWith("au-")).length).toBe(0);
})
.catch(e => { console.log(e.toString()) })
.finally(() => {
component.dispose();
done();
});
});
it("Should render a dynamic text", (done) => {
const randomId = randomIdGenerator();
const component1 = StageComponent
.withResources("ValueText/ValueText")
.inView(`<value-text id='${randomId}' value.bind='boundValue'></value-text>`)
.boundTo({ boundValue: "Hello Value Text" });
component1
.create(bootstrap)
.then(() => {
const strongElement = document.querySelector(`value-text#${randomId}>strong`);
expect(strongElement.textContent.trim()).toBe('Hello Value Text');
})
.catch(e => { console.log(e.toString()) })
.finally(() => {
component1.dispose();
done();
});
});
it("Should render the provided static text without i18nKey", (done) => {
const randomId = randomIdGenerator();
const component2 = StageComponent
.withResources("ValueText/ValueText")
.inView(`<value-text id='${randomId}' value='Hello Static Text'></value-text>`);
component2
.create(bootstrap)
.then(() => {
const strongElement = document.querySelector(`value-text#${randomId}>strong`);
expect(strongElement.textContent.trim()).toBe('Hello Static Text');
})
.catch(e => { console.log(e.toString()) })
.finally(() => {
component2.dispose();
done();
});
});
});
虽然我在这里展示了 ValueText
的测试,但 NormalText
的测试看起来也非常相似。
当我 运行 分别针对这两个元素进行测试时,所有测试 运行 都很好。但是,当它们一起 运行 时,对于某些测试用例,document.querySelector('...')
会返回 undefined
元素。这导致 运行 没有 expect
断言。这导致了以下错误。
Spec 'HERE_GOES_SPEC_NAME' has no expectations.
经过一些调试,似乎当测试 运行 在一起时,对于第二个 运行 的测试套件,甚至没有创建自定义元素的视图。它创建一个 DOM 元素,如下所示。
<normal-text value="Hello Static Text"></normal-text>
但是缺少视图的 innerHTML 部分。更正式地说,在这些测试期间,关联的 viewmodel/controller 在 aurelia-templating 中仍然缺失,这导致了格式错误的视图。
我应该改变什么,使这些测试用例变得确定?
附加信息: 我创建了一个 GitHub repo,以便有兴趣的 reader/user 可以重现该问题。请记住,您可能 运行 多次测试以重现问题。
经过长时间的调试,事实证明,对于失败的测试规范(即 运行 秒后的测试套件),元数据是不正确的。例如,如果 NormalText
的测试套件首先是 运行,那么对于 ValueText
的测试套件,ValueText
的元数据反映了 NormalText
的元数据;更具体地说,NormalText
.
可能某处有错误或我编写测试的方式有问题。
但是,我找到了一个简单的解决方法,即在两个 类 上应用 @customElement("element-name")
装饰器。这确实解决了问题。