既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上软件测试知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
最终的运行结果如下所示:
4.3 包含/排队用例
通过学习Hook,我们可以把测试的前置和后置条件进行剥离,更好的编写和组织测试用例。在实际项目中,我们也需要仅运行指定的测试用例或跳过某些用例等。Cypress也提供相应的功能,一起来看看吧。
4.3.1 包含测试集/测试用例
在Cypress提供该功能的是.only()。当使用.only()指定某个测试集/测试用例后,仅当指定了的测试集/测试用例才会运行,其他未指定的测试集/测试用例则不会运行。示例如下所示:
1.仅运行指定测试集
/// <reference types="cypress" />
describe.only('包含only', () => {
let baseUrl="https://example.cypress.io/todo";
before(()=>{
cy.log("所有用例运行前执行before,仅执行一次");
});
beforeEach(()=>{
cy.log("每个用例执行前,均会执行一次beforeEach");
cy.visit(baseUrl,{timeout:20000});
});
it('测试用例-1', () => {
cy.get(".header input").should("have.class","new-todo");
});
it('测试用例-2', () => {
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
afterEach(()=>{
cy.log("每个用例执行完成后,均会执行afterEach");
});
after(()=>{
cy.log("所有用例运行完成后执行after,仅执行一次");
});
});
describe('不包含only', () => {
let tempUrl="https://www.baidu.com";
beforeEach(()=>{
cy.visit(tempUrl);
});
it('不包含only测试用例-1', () => {
cy.get("#kw").type("Surpass{Enter}");
// cy.get("#kw").type("Surpass");
// cy.get("#su").click();
});
afterEach(()=>{
cy.log("每个用例执行完成后,均会执行afterEach");
});
});
最终的运行结果如下所示:
2.仅运行指定测试用例
describe.only('包含only', () => {
let baseUrl="https://example.cypress.io/todo";
before(()=>{
cy.log("所有用例运行前执行before,仅执行一次");
});
beforeEach(()=>{
cy.log("每个用例执行前,均会执行一次beforeEach");
cy.visit(baseUrl,{timeout:20000});
});
it('测试用例-1', () => {
cy.get(".header input").should("have.class","new-todo");
});
it.only('测试用例-2', () => {
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
afterEach(()=>{
cy.log("每个用例执行完成后,均会执行afterEach");
});
after(()=>{
cy.log("所有用例运行完成后执行after,仅执行一次");
});
});
最终的运行结果如下所示:
4.3.2 排除测试集/测试用例
在Cypress提供该功能的是.skip()。当使用.skip()指定某个测试集/测试用例后,则不会运行该测试集/测试用例,其他未指定的测试集/测试用例则会运行。示例如下所示:
1.排除指定测试集
/// <reference types="cypress" />
describe('包含only', () => {
let baseUrl="https://example.cypress.io/todo";
before(()=>{
cy.log("所有用例运行前执行before,仅执行一次");
});
beforeEach(()=>{
cy.log("每个用例执行前,均会执行一次beforeEach");
cy.visit(baseUrl,{timeout:20000});
});
it('测试用例-1', () => {
cy.get(".header input").should("have.class","new-todo");
});
it.only('测试用例-2', () => {
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
afterEach(()=>{
cy.log("每个用例执行完成后,均会执行afterEach");
});
after(()=>{
cy.log("所有用例运行完成后执行after,仅执行一次");
});
});
describe.skip('不包含only', () => {
let tempUrl="https://www.baidu.com";
beforeEach(()=>{
cy.visit(tempUrl);
});
it('不包含only测试用例-1', () => {
cy.get("#kw").type("Surpass{Enter}");
// cy.get("#kw").type("Surpass");
// cy.get("#su").click();
});
afterEach(()=>{
cy.log("每个用例执行完成后,均会执行afterEach");
});
});
最终的运行结果如下所示:
2.排除指定测试用例
describe('顶层测试集', () => {
let baseUrl="https://example.cypress.io/todo";
before(()=>{
cy.log("所有用例运行前执行before,仅执行一次");
});
beforeEach(()=>{
cy.log("每个用例执行前,均会执行一次beforeEach");
cy.visit(baseUrl,{timeout:20000});
});
it('测试用例-1', () => {
cy.get(".header input").should("have.class","new-todo");
});
it.skip('测试用例-2', () => {
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
describe.skip('嵌套测试集', () => {
it('嵌套测试集用例-1', () => {
cy.log("测试嵌套用例集");
});
});
afterEach(()=>{
cy.log("每个用例执行完成后,均会执行afterEach");
});
after(()=>{
cy.log("所有用例运行完成后执行after,仅执行一次");
});
});
最终的运行结果如下所示:
从上面示例中可以看出,标记为被排除的测试集后,则该测试集所有测试用例均不被执行
在实际项目中,only()和skip()通常是结合着使用,这时我们要先看标记describe的是skip()还是only(),其规则如下所示:
- 如果先标记describe的是skip(),则整个测试用例集都将被排除,不执行
- 如果先标记describe的是only(),若该用例集下,没有任何标记skip的用例,则所有用例都将运行
- 如果先标记describe的是only(),若该用例集下,如果有标记only的用例,则将仅运行标记了only的用例
- 如果describe和it均没有skip/only,则默认运行所有测试集或用例
4.4 动态执行测试用例
前面学习如何排除和执行指定测试集/测试用例,但在一些实际项目中,在执行用例的时候,会根据某一个条件来动态执行测试用例。为了解决这个问题,Cyrpess也提供相应的功能,通过更改相应的测试配置来支持。其语法格式如下所示:
describe(name, config, fn)
context(name, config, fn)
it(name, config, fn)
specify(name, config, fn)
部分配置参数为只读,不支持修改,可参考官网:https://docs.cypress.io/guides/references/configuration##Test-Configuration
1.测试用例集配置
示例代码如下所示:
/// <reference types="cypress" />
describe('When not in Chrome',{browser:"!chrome"}, () => {
let baseUrl="https://example.cypress.io/todo";
it.only('Show warnings', () => {
cy.visit(baseUrl,{timeout:20000});
cy.get(".header input").should("have.class","new-todo");
});
it.only('测试用例-2', () => {
cy.visit(baseUrl,{timeout:20000});
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
});
在Chrome中运行时其结果如下所示:
下面的示例,将仅运行在指定的浏览器中,且指定的分辨率和环境变量将覆盖默认的值,如下所示:
/// <reference types="cypress" />
describe('When in Chrome',
{
browser:"chrome",
viewportWidth: 800,
viewportHeight: 600,
env: {
flag: true,
url: "https://www.surpassme.com",
},
},
() => {
let baseUrl="https://example.cypress.io/todo";
it.only('Show warnings', () => {
cy.visit(baseUrl,{timeout:20000});
cy.get(".header input").should("have.class","new-todo");
});
it.only('测试用例-2', () => {
cy.visit(baseUrl,{timeout:20000});
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
});
运行时其结果如下所示:
2.单个测试用例配置
示例代码如下所示:
/// <reference types="cypress" />
describe('When in Chrome', () => {
let baseUrl="https://example.cypress.io/todo";
it.only('Show warnings',
{
retries: {
runMode: 3,
openMode: 2
}
},
() => {
cy.visit(baseUrl,{timeout:20000});
cy.get(".header input").should("have.class","new-todo");
});
it.only('测试用例-2', () => {
cy.visit(baseUrl,{timeout:20000});
cy.get('.new-todo').type('todo A{enter}').type('todo B{enter}');
cy.get('.todo-list li').should('have.length', 4);
});
});
4.5 动态生成测试用例
在实际项目中,会遇到一种情况,就是多个用例的操作步骤、断言均一样,仅是输入和输出不一样。如果我还是一条数据写一个用例,则效率会非常低。此时,我们可以利用Cypress动态生成测试用例来高效完成。我们以登录为例,如下所示:
1.创建一个postdata.json格式的数据文件
[
{
"title": "测试数据-1",
"customerName": "Surpass",
"telephone": "18812345678",
"email":"ceo@surpass.com"
},
{
"title": "测试数据-2",
"customerName": "kevin",
"telephone": "17808231169",
"email":"hr@surpass.com"
}
]
2.创建测试用例
/// <reference types="cypress" />
import data from "./postdata.json"
describe("测试发送数据", () => {
let baseUrl="http://httpbin.org/forms/post";
beforeEach(()=>{
cy.visit(baseUrl)
});
data.forEach( item => {
it(item.title, () => {
cy.log(item.title,item.customerName,item.telephone)
cy.get(":nth-child(1) > label > input").type(item.customerName).should("contain.value",item.customerName);
cy.get("form > :nth-child(2) > label > input").type(item.telephone).should("contain.value",item.telephone);
cy.get("form > :nth-child(3) > label > input").type(item.email).should("contain.value",item.email);
});
})
})
运行时其结果如下所示:
如果大家对数据驱动比较了解的话,从上面的示例可以看到,是不是非常像?其最大价值为测试数据更改时,不影响测试代码。
4.6 断言风格
Cypress支持两种风格的断言BDD (expect/should) 和TDD (assert),以下列举常见的断言:
1、针对长度(Length)的断言
cy.get('.todo-list li').should('have.length', 4);
2、针对类(Class)的断言
cy.get("form").find("input").should("not.have.class","surpass");
3、针对值(Value)的断言
cy.get("form > :nth-child(3) > label > input").should("contain.value","Surpass");
4、针对文本内容(Text)的断言
cy.get("button").should("contain.text","Submit order");
// 或
cy.get("button").should("not.contain","Surpass");
5、针对元素是否可见(Visible)的断言
cy.get("button").should("be.visible");
6、判断元素是否存在的断言
cy.get("button").should("not.exist");
7、判断元素状态(State)的断言
cy.get(":nth-child(4) > :nth-child(2) > label > input").click().should("be.checked");
8、针对CSS的断言
cy.get(".surpass").should("have.css","line-surpass");
4.7 运行测试用例
4.7.1 运行单个用例
运行单个测试用例,可以获得到更好的性能。在Test Runner界面,点击单个JS文件即可,其操作方法如下所示:
4.7.2 运行所有用例
运行所有测试用例,可以在Test Runner中单击运行Run x integration specs
4.7.3 运行部分用例
可以通过筛选从而仅运行符合筛选条件的用例。
筛选条件中忽略大小写
4.8 测试运行状态
在Cypress中,测试用例的运行状态可以分为4种状态:通过(Passed)、失败(Failed)、等待(Pending)、跳过(Skipped)。
4.8.1 Passed
Passed表示测试用例的运行状态为通过,没有出现断言失败的情况。如下所示:
4.8.2 Failed
Failed表示测试用例的运行状态为失败,有出现断言失败的情况。如下所示:
4.8.3 Pending
当一个测试用例没有想好怎么写时,我们可以写一些占位性质的用例,虽然Cypress不会运行,但却会让后续的用例状态处于Pending状态,如下所示:
/// <reference types="cypress" />
describe('测试Pending场景', () => {
it('未完成的测试用例')
it.skip('已经完成的用例', () => {
let url="http://httpbin.org/forms/post";
let customerName="Surpass",telephone="18812345678",email="ceo@surpass.com",textMsg="I Love Surpass",buttonText="Submit order";
cy.visit(url,{timeout:10000});
cy.get(":nth-child(1) > label > input").type(customerName).should("contain.value",customerName);
cy.get("form > :nth-child(2) > label > input").type(telephone).should("contain.value",telephone);
cy.get("form > :nth-child(3) > label > input").type(email).should("contain.value",email);
cy.get("textarea").type(textMsg).should("contain.value",textMsg);
cy.get("button").should("contain.text",buttonText)
});
xit("另一种测试用例",()=>{
expect(false).to.true;
});
});
运行时其结果如下所示:
以上三种情况的用例均会标识为Pending状态
如果用例编写人员故意使用以上三种方式中的其中一种方式来跳过执行用例,则Cypress将视为Pending Test
4.8.4 Skipped
当一个测试用例本来要执行,但却因为某些原因而未能运行,则Cypress会将该用例的运行状态视为Skipped。我们在一个测试集里面添加beforeEach(),示例代码如下所示:
/// <reference types="cypress" />
describe('测试用例状态为Skipped场景', () => {
let baseUrl="https://example.cypress.io/todo";
beforeEach(()=>{
cy.visit(baseUrl);
});
it('hides footer initially', () => {
cy.get('.filters').should('be.exist');
});
it('adds 2 todos', () => {
cy.get('.new-todo').type('learn testing{enter}').type('be cool{enter}');
cy.get('.todo-list li').should('have.length', 4);
})
});
以上这种情况,所有测试用例能顺利执行并通过,如下所示:
我们修改以上代码,让beforeEach()访问的地址不存在,再来看看,如下所示:
/// <reference types="cypress" />
describe('测试用例状态为Skipped场景', () => {
let baseUrl="https://example.cypress.io/todo";
beforeEach(()=>{
cy.visit(baseUrl+"/does-not-exist");
});
it('hides footer initially', () => {
cy.get('.filters').should('be.exist');
});
it('adds 2 todos', () => {
cy.get('.new-todo').type('learn testing{enter}').type('be cool{enter}');
cy.get('.todo-list li').should('have.length', 4);
})
});
运行结果如下所示:
在上述示例代码中,用例adds 2 todos本来想运行,但却因为beforeEach出现问题,而未能运行,最终被标识为Skipped。
4.9 Test Runner简介
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
ds 2 todos’, () => {
cy.get(‘.new-todo’).type(‘learn testing{enter}’).type(‘be cool{enter}’);
cy.get(‘.todo-list li’).should(‘have.length’, 4);
})
});
运行结果如下所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/36dc4c58e5134319848d140452f8942e.png)
在上述示例代码中,用例adds 2 todos本来想运行,但却因为beforeEach出现问题,而未能运行,最终被标识为Skipped。
### 4.9 Test Runner简介
[外链图片转存中...(img-FMgJ3KPY-1715888390385)]
[外链图片转存中...(img-HPmJG81I-1715888390385)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618631832)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**