Решение для параметризованного тестирования в 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»)

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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().

Это работает, большое спасибо! Возможно, это глупый вопрос, но считается ли это хорошей практикой для тестов в целом?

dmtree 02.07.2024 18:38

Я имею в виду перебор массива и создание тестовых примеров таким образом, а не часть импорта данных.

dmtree 02.07.2024 18:49

Я думаю, что использование данных для реализации сценариев тестирования — довольно распространенная практика. Я мог бы задаться вопросом, имеет ли это ценность в данном конкретном случае (будут ли модульные или интеграционные тесты более разумным вариантом, чем пользовательский интерфейс?). Но в целом, в тех случаях, когда вам нужно повторить одни и те же шаги с разными данными/пользователями/и т. д., я Я бы сказал, что это довольно распространенная практика. Многие другие среды тестирования имеют более надежную поддержку аналогичных практик.

agoff 02.07.2024 19:04

Пожалуйста, ознакомьтесь с рецептом 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);
  })
})
``

Другие вопросы по теме