Skip to content

Cypress - 测试固件

Cypress - 使用 Fixtures 管理测试数据

Section titled “Cypress - 使用 Fixtures 管理测试数据”

Cypress fixtures(测试夹具)用于管理测试可能需要的静态数据。它们通常是存储在 cypress/fixtures 文件夹中的外部文件(例如,JSON、CSV、图像、HTML)。Fixtures 有助于将测试数据与测试逻辑分离,使测试更清晰、更易于维护,尤其适用于数据驱动测试。

默认情况下,Cypress 会在 cypress/fixtures 目录中查找 fixture 文件。你可以在此目录下的子文件夹中组织你的 fixtures。

cy.fixture() 命令用于加载 fixture 文件。它会返回文件的内容,这些内容随后可以在后续的 Cypress 命令或断言中使用。

cy.fixture(filePath)
cy.fixture(filePath, encoding)
cy.fixture(filePath, options)
cy.fixture(filePath, encoding, options)

其中:

  • filePath: fixture 文件路径(相对于 cypress/fixtures 文件夹)。例如,‘user.json’, ‘test-data/credentials.json’。
  • encoding (可选): 要使用的编码(例如,‘utf8’, ‘ascii’)。大多数文本文件默认为 ‘utf8’。对于图像等二进制文件,Cypress 通常会推断编码,或者你可以将其设置为 null。
  • options (可选): 一个对象,用于修改默认行为,例如 timeout。cy.fixture() 的默认超时设置是 fixturesFolder。

假设你在 cypress/fixtures/user.json 中有以下内容:

{
"username": "testUser",
"email": "test@example.com",
"password": "securePassword123"
}

你可以在测试中加载并使用这些数据:

describe('Login Functionality', () => {
it('should login with valid credentials from fixture', () => {
cy.fixture('user.json').then((userData) => {
cy.visit('/login');
cy.get('input[name="username"]').type(userData.username);
cy.get('input[name="password"]').type(userData.password);
cy.get('button[type="submit"]').click();
cy.url().should('include', '/dashboard');
cy.contains(`Welcome, ${userData.username}`).should('be.visible');
});
});
});

在 beforeEach 或 before Hooks 中使用 Fixtures

Section titled “在 beforeEach 或 before Hooks 中使用 Fixtures”

对于在套件中多个测试中使用的数据,通常在 beforeEach 或 before hook 中加载 fixtures。你可以使用 alias (.as()) 或 this 上下文(结合标准 function,而不是 hook/测试中的箭头函数)来使数据可用。

describe('User Profile Tests', () => {
beforeEach(() => {
// Load fixture and alias it
cy.fixture('userProfile.json').as('profileData');
cy.visit('/profile');
});
it('should display user information correctly', function() { // Use 'function' for 'this' context with aliases
// Access aliased data using this.profileData
cy.get('#userNameDisplay').should('contain.text', this.profileData.name);
cy.get('#userEmailDisplay').should('contain.text', this.profileData.email);
});
it('should allow updating profile details', function() {
cy.get('input[name="name"]').clear().type(this.profileData.newName);
// ... other actions
});
});

要使用 this.profileData,测试 (it) 和 hook (beforeEach) 必须是标准函数(function() {}),而不是箭头函数(() => {}),因为箭头函数没有自己的 this 绑定。

直接使用 this 上下文 (传统方法)

Section titled “直接使用 this 上下文 (传统方法)”
describe('Registration Form', function() { // Note: using 'function' for 'this' context
before(function() {
cy.fixture('registrationData.json').then(function(data) {
this.testData = data; // Assign to 'this' context
});
});
it('should fill and submit the registration form', function() {
cy.visit('/register');
cy.get('input[name="fullName"]').type(this.testData.fullName);
cy.get('input[name="email"]').type(this.testData.email);
// ... fill other fields using this.testData
cy.get('button[type="submit"]').click();
cy.contains('Registration successful!').should('be.visible');
});
});

Fixtures 不仅限于 JSON。你可以加载图像、文本文件、HTML 等。

  • 图像: cy.fixture('logo.png').then(fileContent => cy.get('input[type="file"]').attachFile({ fileContent, fileName: 'logo.png', mimeType: 'image/png' })); (使用 cypress-file-upload 插件作为附加文件的示例)。
  • 文本文件: cy.fixture('sample.txt').should('contain', 'Expected text');

Fixtures 对于数据驱动测试至关重要,你可以在其中使用多个数据集运行相同的测试逻辑。

示例: cypress/fixtures/loginCredentials.json

[
{ "username": "validUser", "password": "validPass", "shouldSucceed": true },
{ "username": "invalidUser", "password": "wrongPass", "shouldSucceed": false },
{ "username": "validUser", "password": "", "shouldSucceed": false }
]

测试文件:

describe('Login Data-Driven Tests', () => {
beforeEach(() => {
cy.visit('/login');
});
it('processes multiple login attempts from fixture', () => {
cy.fixture('loginCredentials.json').then((credentialsList) => {
credentialsList.forEach((creds) => {
cy.get('input[name="username"]').clear().type(creds.username || ''); // Handle empty username
cy.get('input[name="password"]').clear().type(creds.password || ''); // Handle empty password
cy.get('button[type="submit"]').click();
if (creds.shouldSucceed) {
cy.url().should('include', '/dashboard');
cy.visit('/login'); // Navigate back for next iteration if needed
} else {
cy.get('.error-message').should('be.visible');
// Clear fields or refresh page as needed for next iteration
cy.reload(); // Simple way to reset for next iteration
}
});
});
});
});

注意:对于更复杂的数据驱动场景,在单个 it 块内迭代可能会使调试变得困难。如果每个数据集都代表一个独特的测试用例,可以考虑动态生成测试。请参阅 Cypress 文档关于动态测试的内容。

进一步阅读: