我们可以直接对 HTML 嵌入式 JavaScript 函数进行单元测试吗?
Can we directly unit test HTML embedded JavaScript functions?
假设我们有一个嵌入了JavaScript的网页,如index.html
,如下所示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<title>Cypress - Testing the Tester</title>
<script>/*<![CDATA[*/
function foo() {
return "bar";
}
function outputMessage(message) {
document.querySelector("output").innerHTML += message + "<br />";
}
window.addEventListener("pageshow", function(){
outputMessage(foo());
});
/*]]>*/</script>
</head>
<body>
<h1>Cypress - Testing the Tester</h1>
<output></output>
</body>
</html>
在页面显示(例如加载)中,这会在 <output></output>
.
中插入字符串“bar”
如果my_cypress_spec.js
是:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
expect(foo()).to.equal("bar");
});
});
然后在赛普拉斯测试运行器中我得到一个“ReferenceError ... foo is not defined”。也就是说,赛普拉斯似乎无法识别 foo()
函数。
有没有办法让 Cypress 直接对 foo()
函数进行单元测试?也就是说,不依赖 ES6/ES2015 export/imports(上面的重构将 foo()
放在它自己的 JavaScript 文件中,然后 my_cypress_spec.js
导入它)?
正在尝试 我的 my_cypress_spec.js
变成:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
cy.window().then(win => {
expect(win.foo()).to.eq('bar');
});
});
});
我收到错误“TypeError ... win.foo 不是一个函数”。
我不确定如果您使用更复杂的应用程序(例如使用 Angular 或 React 创建的应用程序),这将适用于何种程度。这些框架具有专门用于单元测试的测试工具。
对于您提供的原始 JS 示例,这很容易,因为 foo()
附加到 AUT 的 window。
cy.window().then(win => {
expect(win.foo()).to.eq('bar')
})
Fody 的回答有效。所以,完整的 my_cypress_spec.js
可以变成这样的:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
cy.window().then(win => {
expect(win.foo()).to.eq('bar');
});
});
});
但是,我收到“TypeError ... win.foo is not a function”的原因是因为在我机器上的 index.html
中(不是上面最初发布的那样)我有一个开幕 <script type="module">
。将其改回 <script>
使测试通过。
因此,为了完整起见,我将其标记为“答案”,同时指出来自@Fody 和@jonrsharpe 的见解。
假设我们有一个嵌入了JavaScript的网页,如index.html
,如下所示:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<title>Cypress - Testing the Tester</title>
<script>/*<![CDATA[*/
function foo() {
return "bar";
}
function outputMessage(message) {
document.querySelector("output").innerHTML += message + "<br />";
}
window.addEventListener("pageshow", function(){
outputMessage(foo());
});
/*]]>*/</script>
</head>
<body>
<h1>Cypress - Testing the Tester</h1>
<output></output>
</body>
</html>
在页面显示(例如加载)中,这会在 <output></output>
.
如果my_cypress_spec.js
是:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
expect(foo()).to.equal("bar");
});
});
然后在赛普拉斯测试运行器中我得到一个“ReferenceError ... foo is not defined”。也就是说,赛普拉斯似乎无法识别 foo()
函数。
有没有办法让 Cypress 直接对 foo()
函数进行单元测试?也就是说,不依赖 ES6/ES2015 export/imports(上面的重构将 foo()
放在它自己的 JavaScript 文件中,然后 my_cypress_spec.js
导入它)?
正在尝试 my_cypress_spec.js
变成:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
cy.window().then(win => {
expect(win.foo()).to.eq('bar');
});
});
});
我收到错误“TypeError ... win.foo 不是一个函数”。
我不确定如果您使用更复杂的应用程序(例如使用 Angular 或 React 创建的应用程序),这将适用于何种程度。这些框架具有专门用于单元测试的测试工具。
对于您提供的原始 JS 示例,这很容易,因为 foo()
附加到 AUT 的 window。
cy.window().then(win => {
expect(win.foo()).to.eq('bar')
})
Fody 的回答有效。所以,完整的 my_cypress_spec.js
可以变成这样的:
describe('The Home Page Tests', () => {
it('Test HTML embedded JavaScript function', () => {
// Assumes, e.g. "baseUrl": "http://127.0.0.1:5500" set in cypress.json
cy.visit('index.html');
cy.window().then(win => {
expect(win.foo()).to.eq('bar');
});
});
});
但是,我收到“TypeError ... win.foo is not a function”的原因是因为在我机器上的 index.html
中(不是上面最初发布的那样)我有一个开幕 <script type="module">
。将其改回 <script>
使测试通过。
因此,为了完整起见,我将其标记为“答案”,同时指出来自@Fody 和@jonrsharpe 的见解。