cypress-api-教程
文章《使用 Cypress 进行 REST API 测试》中创建的存储库
接下来,让我们继续讨论上一篇文章中提到的主题,重点关注对我们来说最重要的部分——测试。
基于微服务的应用程序的资源可以通过多种方式进行操作。可以创建、更新、删除资源,以及执行其他操作。
当我们发送服务请求时,需要通过 URI 来告知服务请求方我们要处理的资源。我们还需要告知服务请求方我们要对资源执行的操作类型。为此,我们将使用 HTTP 协议方法。
HTTP 协议有多种方法,每种方法的功能各不相同。最常用的方法有:
回到我们的目标 API—— ServeRest,让我们首先测试用户的端点:
/usuarios检索所有用户数据。好了,都给我动起来!开始吧!
我们将从 Integration 文件夹中删除上一篇文章中的所有内容。我们的测试代码应该放在那里,所以我们只保留必要的代码。
你可以手动删除,或者如果你像我一样懒,可以使用下面的命令:
rm -rf cypress/integration/*
现在我们将创建一个名为 `<user_endpoint>` 的文件夹Usuarios,用于存储所有与用户端点相关的请求。这将有助于我们保持代码的条理性和组织性。
在文件夹内Usuarios,我们将创建我们的第一个测试规范,名为GETusuarios.spec.js
现在项目结构应该如下所示:
├── fixtures
├── integration
│ └── Usuarios
│ └── GETUsuarios.spec.js
├── plugins
│ └── index.js
├── support
│ ├── commands.js
│ └── index.js
└── videos
让我们添加 Mocha 的基本组织结构。如果需要,您可以使用 BDD 风格:
Given->测试套件名称When->测试内部套件名称Then你应该把你的测试放在这里!
/// <reference types="cypress" />
describe('Given the Users api', () => {
context('When I send GET /usuarios', () => {
it('Then it should return a list with all registered users', () => {
// place your tests here
});
});
context('When I send GET /usuarios passing id query param', () => {
it('Then it should return only the filtered user', () => {
// place your tests here
});
});
});
现在让我们使用 Cypress 方法cy.request发出 HTTP 请求:
cy.request({
method: 'GET',
url: ' https://serverest.dev/usuarios '
})
After that we will call the `.should` function, which I mentioned in the previous post. It will enable us to make multiple assertions on the yielded subject - **response** in this case.
```javascript
.should((response) => {
// all your assertions should be placed here!!
});
让我们添加一条日志,看看“响应”在正文中返回了什么:
cy.log(JSON.stringify(response.body))
简而言之,cy.log它将访问响应的“body”属性。该JSON.stringify函数将用于把响应体转换为字符串。
运行该命令cypress:open并查看日志返回的内容。
npm run cypress:open
太棒了!我们可以得出结论,我们的调用工作正常,因为我们正确收到了响应正文和 200 状态码(成功)。
让我们移除cy.log(我们不希望测试中出现垃圾数据),并添加一些状态码和响应体断言。
我们可以先验证最简单的那个,即状态码:
expect(response.status).to.eq(200)
太好了!上面的代码表示我们期望响应的状态码等于 200。
我们可以断言,quantidade (数量)键始终与usuarios (用户)数组中的元素个数相同。让我们添加以下验证:
expect(response.body.quantidade).to.eq(response.body.usuarios.length)
让我们验证一下“email发件人”字段usuarios是否不能为空……
嗯,但是
usuarios这是一个包含三个元素的列表。那我们该怎么做呢?
我们需要传递要usuarios访问的列表索引才能做到这一点。现在,让我们访问列表中的第一个对象,传递 'usuarios[0]':
expect(response.body.usuarios[0].email).to.not.be.null
太好了,成功了!但是我们如何确保usuarios数组中所有对象的“email”键都不为空呢?
或许可以复制上一行,只需更改索引即可?
expect(response.body.usuarios[0].email).to.not.be.null
expect(response.body.usuarios[1].email).to.not.be.null
是的,这或许可行。但是,如果这个数组里有上千个用户呢?难道我们要在代码里增加上千行吗?
我不这么认为。
为了进行更智能的断言,我们可以使用Cypress loadash,它为我们提供了以下.each()函数:
Cypress._.each(response.body.usuarios, (usuario) => {
expect(usuario.email).to.not.be.null
})
这个函数几乎就像 forEach() 一样工作,遍历数组并对 'usuarios' 数组中的每个 'usuario' 对象进行断言。
让我们借此机会添加最后一个验证usuarios。我们期望每个对象都包含所有键('nome'、'email'、'password'、'administrador'、'_id'):
expect(usuario).to.have.all.keys('nome', 'email', 'password', 'administrador', '_id')
接下来,我们将发送与之前相同的请求,但这次会传递一个参数,query string以便仅按以下条件筛选出一个用户_id:
添加验证以确保名称始终正确:
context('When I send GET /usuarios passing id query param', () => {
it('Then it should return only the filtered user', () => {
cy.request({
method: 'GET',
url: 'https://serverest.dev/usuarios',
qs: {
_id: '0uxuPY0cbmQhpEz1'
}
})
.should((response) => {
expect(response.status).to.eq(200)
expect(response.body.usuarios[0].nome).to.eq("Fulano da Silva")
});
});
});
我们url在两个文件中都重复使用了该参数cy.request()。请将以下几行添加到您的cypress.json文件中,这样就无需重复输入这些信息了。
也设置video好false了。我们不想让 Cypress 帮我们录制。
{
"baseUrl": "https://serverest.dev",
"video": false
}
好的,这算是一个好的开始,现在我们的代码看起来是这样的:
/// <reference types="cypress" />
describe('Given the Users api', () => {
context('When I send GET /usuarios', () => {
it('Then it should return a list with all registered users', () => {
cy.request({
method: 'GET',
url: '/usuarios'
})
.should((response) => {
expect(response.status).to.eq(200)
expect(response.body.quantidade).to.eq(response.body.usuarios.length)
Cypress._.each(response.body.usuarios, (usuario) => {
expect(usuario.email).to.not.be.null
expect(usuario).to.have.all.keys('nome', 'email', 'password', 'administrador', '_id')
})
});
});
});
context('When I send GET /usuarios passing id query param', () => {
it('Then it should return only the filtered user', () => {
cy.request({
method: 'GET',
url: '/usuarios',
qs: {
_id: '0uxuPY0cbmQhpEz1'
}
})
.should((response) => {
expect(response.status).to.eq(200)
expect(response.body.usuarios[0].nome).to.eq("Fulano da Silva")
});
});
});
});
请注意,我们向同一个端点发送了两个请求。这需要重构,但我们稍后再讨论这个问题。
接下来,我们将介绍下一个 HTTP 方法。为此,我们将创建一个名为 POSTUsuarios.spec.js 的新文件。我们将把所有与 POST 方法相关的测试都放在这个文件中。
使用 Mocha 函数创建测试结构,就像我们在 GET 文件中所做的那样。显然,需要根据场景修改描述describe。contextit
/// <reference types="cypress" />
describe('Given the Users api', () => {
context('When I send POST /usuarios', () => {
it('Then it should create a new user', () => {
});
});
});
这次的cy.request()功能会略有不同。
POST……/users(无需添加完整的 URL,只需添加资源即可)。body参数中,我们将添加创建新用户所需的信息。要了解需要哪些信息,请务必查阅ServeRest的 API 文档。我们的有效载荷将如下所示:
body: {
nome: "Dumb John",
email: "dumb.john@qa.com.br",
password: "test",
administrador: "true"
}
让我们借此机会验证一下成功消息和状态码。
/// <reference types="cypress" />
describe('Given the Users api', () => {
context('When I send POST /usuarios', () => {
it('Then it should create a new user', () => {
cy.request({
method: 'POST',
url: '/usuarios',
body: {
nome: "Dumb Joe",
email: "dumb.joe@qa.com.br",
password: "test",
administrador: "true"
}
})
.should((response) => {
expect(response.status).eq(201)
expect(response.body.message).eq("Cadastro realizado com sucesso")
});
});
});
});
成功!确定吗?请再运行一次测试。
当我们再次运行测试时,它失败了,这是为什么呢?这是因为根据业务规则,不允许使用已使用的电子邮件地址注册用户。让我们使用一种策略来解决这个问题。
让我们编辑位于以下位置的文件:plugins > index.js
我们将使用 libFaker为每个请求创建一个不同的用户。faker使用以下npm命令安装:
npm i -D faker
我将其命名task为freshUser(),在它里面我们将使用fakerlib 传递键/值:
freshUser() {
user = {
nome: faker.name.firstName(),
email: faker.internet.email(),
password: faker.internet.password(),
administrador: "true"
};
return user;
}
完整文件如下所示:
/// <reference types="cypress" />
const faker = require("faker");
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
on("task", {
freshUser() {
user = {
nome: faker.name.firstName(),
email: faker.internet.email(),
password: faker.internet.password(),
administrador: "true"
};
return user;
}
})
return config
}
现在重构POSTUsuarios.spec.js以使用faker。创建一个名为的变量fakeUser。
let fakeUser;
为了在每次执行之前创建不同的有效载荷,我们将使用一个名为 `.` 的钩子。在这个钩子中,我们将调用由任务创建的抛出beforeEach()函数,并将结果传递给变量。cy.task()userfakeUser
beforeEach(() => {
cy.task('freshUser').then((user) => {
fakeUser = user;
cy.log(JSON.stringify(fakeUser))
});
});
我还添加了一个功能,
cy.log()用于查看每个请求创建的用户。请从您的代码中删除此部分。
将主体参数更改为接收fakeUser变量。
cy.request({
method: 'POST',
url: '/usuarios',
body: fakeUser
})
重构后的文件如下所示:
/// <reference types="cypress" />
let fakeUser;
describe('Given the Users api', () => {
beforeEach(() => {
cy.task('freshUser').then((user) => {
fakeUser = user;
cy.log(JSON.stringify(fakeUser))
});
});
context('When I send POST /usuarios', () => {
it('Then it should create a new user', () => {
cy.request({
method: 'POST',
url: '/usuarios',
body: fakeUser
})
.should((response) => {
expect(response.status).eq(201)
expect(response.body.message).eq("Cadastro realizado com sucesso")
});
});
});
});
现在我们可以根据需要运行任意次数的测试。
我就先写完这篇文章了,因为这里已经有很多信息了!
请记住,仅仅阅读这篇文章并不能让你学会。你需要自己编写代码、练习、失败,直到成功为止!
欢迎在LinkedIn上加我好友。请留下您的评论、问题和建议。
感谢您的关注,我们下篇文章再见!
文章来源:https://dev.to/murillowelsi/api-testing-with-cypress-part-2-creating-your-tests-270i