[Перевод] Управляемое данными тестирование с использованием Cucumber

371fc3abb84041c3d4ddb2332497bc86.jpeg

Cucumber — это фреймворк для тестирования, который поддерживает подход Data-Driven. 

Что такое тестирование, управляемое данными?

Data-Driven Testing, DDT — это подход к тестированию программного обеспечения, при котором для управления процессом тестирования используются наборы данных. Этот подход предполагает тестирование приложения с помощью ряда входных значений, каждое из которых предназначено для проверки определенной фичи или функциональности приложения.

Зачем прибегать к этому виду тестирования?

У тестировщиков часто есть несколько наборов данных, которые используются для одного теста, и создание отдельных тестов с этими различными наборами данных может занять много времени. Этот тип тестирования позволяет выполнить тест–кейс несколько раз с различными наборами данных (входными данными) и проверочными значениями.

Применение Data-driven тестирования целесообразно по следующим причинам:

  1. Приводит к увеличению тестового покрытия — использование в качестве входных данных различных наборов данных позволяет охватить широкий спектр сценариев и комбинаций входных данных.

  2. Дает возможность повторно использовать тестовые скрипты — тестовые скрипты разрабатываются с учетом возможности их повторного использования, что позволяет выполнять их с несколькими наборами входных данных.

  3. Помогает быстрее находить баги — тестирование различных комбинаций входных данных позволяет быстро выявить баги и аномалии в системе на этапе тестирования. 

Тестирование на основе данных дает нам множество преимуществ. Однако, как и любой другой подход, оно имеет ряд потенциальных «подводных камней» и проблем, которые следует учитывать:

  1. Управление набором входных данных — управление большим набором файлов входных данных может быть трудоемким и сложным.

  2. Валидность тестовых данных — наиболее важным моментом является наличие валидных наборов тестовых данных, в противном случае можно получить неточные результаты тестирования, ложноположительные или ложноотрицательные.

  3. Сопровождение и обновление: по мере развития системы тестовые скрипты необходимо актуализировать, а управление тестовыми скриптами и тестовыми данными может оказаться сложной задачей. 

Data-driven тестирование в Cucumber

Cucumber поддерживает управляемое данными тестирование с помощью раздела Scenario Outline и примеров. Scenario Outline — это мощная фича, которая позволяет запускать один и тот же сценарий с различными входными данными или наборами данных. Она позволяет написать один сценарий с плейсхолдерами в полях для ввода текста, а Cucumber автоматически сгенерирует несколько сценариев, заменив эти плейсхолдеры реальными данными.

Использование шаблона сценария для написания сценария тестирования

Ниже приведен пример сценария тестирования для сравнения двух CSV-файлов с использованием шаблона сценария.

Фича: Сравнение данных в csv-файлах


   Схема сценария: Сравнение двух CSV-файлов
     Даны два файла с входными данными "" и "".
     Когда мы сравниваем эти два файла
     Содержимое первого файла должно "" содержимому второго.


     Примеры:
       | file1 | file2 | matchOrNot |
       | input1.csv | input2.csv | match |
       | input3.csv | input4.csv | not match |

В данном примере шаблон сценария задается в фича-файле с плейсхолдерами для указания части путей к CSV-файлам и ожидаемых результатов совпадений. Ключевое слово Scenario Outline используется для указания того, что у нас есть сценарий с несколькими примерами. Таблица примеров определяется с помощью ключевого слова Examples и содержит различные наборы входных данных, которые мы хотим сравнить.

import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;


import static org.junit.Assert.assertEquals;
 
public class Steps {
    private static final String INPUT_DATA_PATH = "./src/test/resources/inputData/";
    private String path1;
    private String path2;
    private boolean filesMatch;


    @Given("two input files {string} and {string}")
    public void getPathToCsvFiles(String fileName1, String fileName2) {
        this.path1 = INPUT_DATA_PATH + fileName1;
        this.path2 = INPUT_DATA_PATH + fileName2;
    }






   
    @When("we compare those two files")
    public void compareFiles() {
        filesMatch = compareCSVFiles(path1, path2);
    }


    @Then("the content from first input should {string} the content from the second one")
    public void filesShouldMatchOrNot(String matchOrNot) {
        boolean expectedMatch = matchOrNot.equals("match");
        assertEquals(expectedMatch, filesMatch);
    }


    private boolean compareCSVFiles(String file1Path, String file2Path) {


        try (BufferedReader reader1 = new BufferedReader(new FileReader(file1Path));
             BufferedReader reader2 = new BufferedReader(new FileReader(file2Path))) {


            String line1, line2;
            int lineCount = 1;


            while ((line1 = reader1.readLine()) != null && (line2 = reader2.readLine()) != null) {
                if (!line1.equals(line2)) {
                    return false;                }
                lineCount++;
            }


            // Verify if there are any unprocessed lines remaining in the fields
            if (reader1.readLine() != null || reader2.readLine() != null) {
                return false;
            }


            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}

Файл с определением шагов («Steps.java») содержит реализацию определений шагов, которые соответствуют шагам шаблона сценария. На шаге getPathToCsvFiles задаются пути к файлам, на шаге compareFiles производится сравнение файлов, а на шаге filesShouldMatch проверяется ожидаемый результат совпадения. 

На шаге compareFiles мы вызываем метод compareCsvFiles, который сравнивает файлы с входными данными построчно. Он возвращает булево значение true, если все строки в файлах с входными данными одинаковы, и false в противном случае.  

Чтобы сравнить два файла с входными данными, мы можем использовать исполнитель тестов Cucumber на основе предоставленных примеров.

import io.cucumber.junit.CucumberOptions;
import net.serenitybdd.cucumber.CucumberWithSerenity;
import org.junit.runner.RunWith;


@RunWith(CucumberWithSerenity.class)
@CucumberOptions(
        features = "src/test/resources/compareCsvFiles.feature",
        plugin = {"pretty"},
        glue = {"steps"}
)
public class Runner {
}

Заключение

Тестирование на основе данных позволяет сократить объем ручных действий, необходимых для проведения тестирования, а также упростить управление и сопровождение тест-кейсов. В целом использование тестирования на основе данных позволяет повысить качество программного обеспечения и гарантировать, что оно соответствует требованиям и ожиданиям пользователей.

В завершение всех QA-инженеров приглашаем на ближайшие открытые уроки, на которых разберем темы:

© Habrahabr.ru