Решение для параметризованного тестирования в Cypress

Я пытаюсь объединить несколько тестов с одинаковыми действиями и проверками, используя параметризованное тестирование, но продолжаю получать ошибки. Я новичок в Cypress и JS в целом, имея опыт работы с .net. Любая помощь будет оценена по достоинству.

Моя приставка выглядит примерно так:

{
  "username": "username",
  "password": "password",
  "inputErrorMessageText": "Invalid username or password.",
  "homePageWelcomeText": "Welcome, bla bla bla",
  "testCases": [
    {
      "description": "blank username and password",
      "username": "",
      "password": ""
    },
    {
      "description": "blank password",
      "username": "username",
      "password": ""
    }
  ]
}

Я пробовал как Cypress.each, так и data.testCases.forEach:

describe("Tests for login page", () => {
    let loginPage;
    let homePage;
    let data;

    before(() => {
        cy.fixture("login_data").then((fixtureData) => {
            data = fixtureData;
            cy.wrap(fixtureData).should("have.property", "testCases");
        });
    });

    beforeEach(() => {
        loginPage = new LoginPage();
        homePage = new HomePage();
        cy.visit("/");
    });

    Cypress.each(data.testCases, (testCase) => {
        it(`Invalid username or password error appears when attempting login with ${testCase.description}`, () => {
            loginPage.login(testCase.username, testCase.password);
            loginPage.verifyErrorMessage(data.inputErrorMessageText);
        });
    });

    it("Successful login with valid username and password", () => {
        loginPage.login(data.username, data.password);
        homePage.verifyProfileDropDownExists();
    });

    it("Welcome text is displayed after successful log in", () => {
        loginPage.login(data.username, data.password);
        homePage.verifyWelcomeText(data.homePageWelcomeText);
    });
data.testCases.forEach((testCase) => {
    it(`Invalid username or password error appears when attempting login with ${testCase.description}`, function () {
        loginPage.login(testCase.username, testCase.password);
        loginPage.verifyErrorMessage(data.inputErrorMessageText);
    });
});

Продолжайте получать следующую ошибку:

TypeError: следующая ошибка возникла из-за вашего тестового кода, а не из Cypress. > Невозможно прочитать свойства неопределенного значения (чтение «testCases»)

🤔 А знаете ли вы, что...
JavaScript является одним из трех основных языков веб-разработки, вместе с HTML и CSS.


1
63
2

Ответы:

Решено

Проблемы

  1. (Это главный виновник) Непосредственное использование data.testCases.forEach() не работает, поскольку Cypress (Mocha, но тут не помешает) должен знать, какие тесты запускать, прежде чем тесты действительно начнут выполняться. В этом случае, поскольку data.testCases не будет иметь значения, когда Cypress начнет собирать тесты для запуска (поскольку данные задаются в блоке before()), он выдает ошибку, когда data.testCases не определено.
  2. Я не думаю, что Cypress.each — это функция. Есть Cypress._.each() (с использованием Cypress Lodash) и cy.each() (это не то, что вам нужно).

Решение

Импортируйте фикстуру напрямую, вместо того, чтобы загружать ее через cy.fixture(), что должно предоставить вам доступ к переменной data.testCases до того, как Cypress определит, какие тесты запускать. Тогда у вас появится возможность запускать несколько тестов либо через data.testCases.forEach(), либо через Cypress._.each().

import data from '../path/to/data.json';

describe("Tests for login page", () => {
  ...
  Cypress._.each(data.testCases, (testCase) => {
    it(`Invalid username or password error appears when attempting login with ${testCase.description}`, () => {
            loginPage.login(testCase.username, testCase.password);
            loginPage.verifyErrorMessage(data.inputErrorMessageText);
        });
  });
});

Вы по-прежнему можете запустить проверку данных, которые data имеют свойство testCases, без cy.fixture().


Пожалуйста, ознакомьтесь с рецептом Cypress фундаментальные принципы__dynamic-tests/cypress/e2e /fixture-spec.cy.js .

/// <reference types = "cypress" />
describe('generated from fixture', () => {
  // We cannot load JSON file using "cy.fixture"
  // because it means the test is already running.
  // Same with using "before" hook - new tests cannot be created from "before" hook.
  // Instead we need to load JSON file using "require" at the start time
  // and generate tests.
  const colors = require('../fixtures/colors')
  const rainbow = ['red', 'orange', 'yellow', 'green', 'blue', 'violet']

  colors.forEach((color) => {
    it(`🌈 has color ${color}`, () => {
      cy.wrap(color).should('be.oneOf', rainbow)
    })
  })
})

Хотя прибор технически исправен, я бы предложил поместить данные в начало теста.

Это гораздо более читабельно, поэтому вы можете легко рефакторить и добавлять случаи. Плюс вы можете включить ожидаемую ошибку там же.

const testCases = [
    {
      "description": "blank username and password",
      "username": "",
      "password": "",
      "error": "user name must be filled in"
    },
    {
      "description": "blank password",
      "username": "username",
      "password": "",
      "error": "password must be filled in"
    },
    {
      "description": "invalid username",
      "username": "not-a-valid-user",
      "password": "pword",
      "error": "username or password is incorrect, please try again"
    }
  ]

testcases.forEach((case) => {
  
  it(case.description, () => {
    loginPage.login(login.username, login.password);
    loginPage.verifyErrorMessage(case.error);
  })
})
``