有人可以解释将Jasmine测试运行器集成到React应用程序中的正确方法(不添加Karma)吗?我将测试用例部署到电视上,并在电视机上运行独立的规范运行器。我必须内联并编译JS,这是我遇到麻烦的地方。我最终手动将jasmine.js,jasmine-html.js和boot.js文件串联到jasmine-all.js文件中,并插入如下调用以定义jasmineRequire:
jasmineRequire = getJasmineRequireObj();
这恰好在内联jasmine-html.js之前。然后,我在React根组件中添加了一个代码片段,以像这样加载整个内容:
componentDidMount() {
import('./jasmine/lib/jasmine-3.2.1/jasmine-all')
.then(() => {return import('./spec/MyAppSpec');});
}
我在这里使用动态导入来保证执行顺序。这个想法是允许应用程序加载,然后加载测试运行器,然后最终加载功能测试,这些测试将整个应用程序作为一个整体。这些测试会将关键事件和输入发送给应用程序,就像最终用户一样。
我知道有一种不太麻烦的方法可以做到这一点,但我无法弄清楚。我想以正确的方式执行此操作,以便可以正确包含任何规范帮助程序文件,这些文件目前已直接导入到我的规范文件中。任何指导都将不胜感激!
答案 0 :(得分:3)
即使对诸如API请求之类的所有异步操作都进行了存根,也无法保证应用程序在根组件componentDidMount
中达到了稳定状态。应该以相反的方式完成,即在测试中初始化应用程序,然后等待其稳定。
Jasmine中没有用于功能/端到端测试的内置功能,必须从头开始编写。
类似于:
async function waitForElement(selector, parent = document, timeout = 2000) {
let isTimeout;
setTimeout(() => {
isTimeout = true;
}, timeout);
let el;
while (!(el = parent.querySelector(selector))) {
if (isTimeout) throw new Error('timeout');
await new Promise(resolve => setTimeout(resolve, 50));
}
return el;
}
const root = document.getElementById('root');
beforeEach(() => {
ReactDOM.render(<App/>, root);
});
afterEach(() => {
ReactDOM.unmountComponentAtNode(root);
});
it('should have foo child', async () => {
const foo = await waitForElement('div.foo', root, 5000);
expect($(foo).text()).toContain('foo text');
});
测试是基于承诺的,并且依赖于等待结果出现在DOM中,因为这可能是异步发生的。
waitForElement
仅作为参考提供,因为它不足以进行实际的E2E测试;需要querySelector
(可以用jQuery增强)或自定义谓词功能不支持的高级选择器。
这是E2E框架(如TestCafe和Protractor)应具有的功能,此功能的可用性与用于单元测试的框架不同。例如。 TestCafe具有reusable and chainable selectors,可以在需要元素的位置进行隐式处理。