Теперь у меня есть в моем личном репозитории GitHub способ, которым вы можете задавать мне вопросы, связанные с темой разработки качества.
Рафаэль Тейшейра прислал мне вопрос относительно подхода к управлению данными |/. Поскольку эта тема очень интересна, я создал этот пост в блоге на основе своих ответов и объяснений.
Какой тип управления лучше в какой ситуации? Когда лучше восстанавливать базу данных без данных? Обычно это зависит от вашего контекста (вашей текущей ситуации в вашем проекте). Мне нравится использовать независимо от проекта, это подделывает генерацию данных и также использует статические файлы.
Когда лучше всего запускать сценарии для определения конкретной конфигурации? И главное, когда система очень большая и сложная и требует нескольких настроек, что делать? На мой взгляд, лучший способ настроить данные в вашем тесте – это во время определения предварительного условия ваших тестов, чтобы вы могли совместно использовать одно и то же условие вместе с тестами, которые имеют общее условие данных. Я сталкиваюсь с той же “проблемой”, что и вы: система, которую я тестирую, очень большая и имеет разные условия передачи данных. Подход, который мы применяем, заключается в том, чтобы сгруппировать связанные тесты в одни и те же предварительные условия. Мы создаем базовый тестовый класс с предварительными и последующими условиями для этой ситуации.
Пример: система может запускать функциональные возможности с уровнями утверждений или без них, при этом для утверждений требуется дополнительная конфигурация, другая настройка данных и т.д… У нас есть два разных базовых тестовых класса, основанных на этих потребностях, поэтому мы можем легко управлять изоляцией этих условий (конфигурация, данные и т.д.)
Обычно я использую 3 разных подхода к управлению данными…
Генерация поддельных данных
Это самый простой способ, которым я пользуюсь все время. Вы можете использовать библиотеку генерации данных, чтобы передать ей ответственность. Я использую Java-мошенник . Вместо того, чтобы создавать данные внутри тестового кода (иногда я это делаю) Я использую этот подход:
- Я создаю объект, который хочу смоделировать
- Я создаю шаблон Builder для этой модели
- Я создаю класс фабрики данных для создания объекта с учетом условий Я могу создавать
Модель даст вам возможность легко создать объект с необходимыми данными, Сборка позволит вам легко получать и устанавливать данные, Класс фабрики данных предоставит вам гибкость для создания другого набора данных и централизованной точки, позволяющей изменять его при необходимости.
Примеры
Давайте представим, что нам нужно добавить возраст человека, чтобы он мог подать заявление на получение водительских прав. Я буду считать, что возраст должен быть.
Объект
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Строитель
public class PersonBuilder { private String name; private int age; public PersonBuilder setName(String name) { this.name = name; return this; } public PersonBuilder setAge(int age) { this.age = age; return this; } public Person build() { return new Person(name, age); } }
Фабрика данных
public class PersonFactory { private final Faker faker; public PersonFactory() { faker = new Faker(); } public Person personAbleToGetDriverLicense() { return new PersonBuilder(). setName(faker.name().fullName()). setAge(faker.number().numberBetween(16, 65)). build(); } public Person personNotAbleToGetDriverLicense() { return new PersonBuilder(). setName(faker.name().fullName()). setAge(faker.number().numberBetween(0, 16)). build(); } }
Вы не можете использовать класс Data Factory в своих тестах для генерации каких-либо данных. В приведенном ниже примере вы можете увидеть использование personAble Для получения водительских прав
, которое вернет объект Person
с возрастом
от 16 до 65 лет, поэтому вам не нужно заполнять, создавать атрибут для этого или генерировать весь объект, как мы это сделали на фабрике данных, в ваш тест.
public class PersonTest { @Test public void personCanApplyForDriverLicense() { PersonFactory personFactory = new PersonFactory(); Person person = personFactory.personAbleToGetDriverLicense(); person.getAge(); // your test goes here } }
Использование статических файлов
Я не так часто использую этот подход но я думаю, что это хороший вариант, и его нужно использовать, если у вас есть такая необходимость. Вы можете использовать различные статические файлы для получения данных, которые вы хотите использовать в своих тестах, например txt
, csv-файл
, json
, yaml
и т.д… При таком подходе вам нужна либо библиотека, которая может читать файл, либо создать класс для этого.
Имейте в виду, что:
- все статические файлы (по крайней мере, в проектах Java) должны быть помещены в папку
resource
, а не вместе с вашим исходным кодом - вы можете постоянно изменять его, чтобы он мог следовать вашему процессу PR (change -> commit -> push -> approve), чтобы включить его в вашу основную ветку
В приведенном ниже примере я использую файл csv
и встроенную функцию JUnit 5 для чтения CSV-файла, предоставленного библиотекой junit-jupiter-params с именем CSVFileSource
CSV-файл
product,amount Micro SD Card 16Gb,6.09 JBL GO 2,22.37 iPad Air Case, 14.99
Тест
class JUnitCSVSourceTest { private static final String MAXIMUM_PRICE = "30.0"; @CsvFileSource(resources = "/products.csv", numLinesToSkip = 1) void productsLassThan(String product, BigDecimal amount) { assertThat(product).isNotEmpty(); assertThat(amount).isLessThanOrEqualTo(new BigDecimal(MAXIMUM_PRICE)); } }
Файл @CSVFileSource
считывает содержимое файла, помещенного в resources
, который должен находиться в папке resources
, и пропускает первую строку, потому что в файле CSV первая строка является заголовком.
Динамическое потребление
У меня был такой подход в моем последнем проектном опыте в финансовом учреждении, где нам нужны разные наборы данных, основанные на разных требованиях. Примеры:
- счет с кредитной картой
- счет с лимитом более 10 000 долларов США и инвестициями
У нас была реплика производственной базы данных, где разработчики (серверная часть и отдел контроля качества), когда требовались какие-то данные, выполняли этот ручной процесс:
- запрос к базе данных-реплике с помощью SQL-скрипта
- обновление данных в тестовом или статическом файле
- запуск тестов
Это также был ручной процесс (настройка данных) перед регрессионным тестом… вы же видите, что это отнимает много времени.
Решение, которое у нас было в то время, состояло в том, чтобы создать DSL для автоматического запроса на основе необходимых нам требований к данным.
public class MyTestWithDynamicData { @Test void cannotPayWithExpiredCreditCard() { DynamicData dynamicData = new DynamicData(); CreditCard creditCard = dynamicData.creditCard().withRestriction(Restriction.EXPIRED); // extraction the credit card information to use in the test String holderName = creditCard.getHolderName(); String creditCardNumber = creditCard.getNumber(); String expirationDate = creditCard.getExpirationDate(); String cvv = creditCard.getCvv(); } }
В приведенном выше примере нам нужна была кредитная карта с уже истекшим сроком действия. Метод с ограничением
получил ограничение . ИСТЕК СРОК действия
и добавил в запрос операторы SQL ( where
предложение), чтобы вернуть объект, соответствующий этим критериям.
Мы можем применять различные подходы к получению данных. Я не упомянул (потому что сейчас я не использую этот подход) еще один, который заключается в том, чтобы генерировать данные, потребляющие и API.
Если у вас есть какие-либо вопросы, пожалуйста, не стесняйтесь комментировать этот пост или присылайте мне вопрос .
Спасибо, что уделили мне время!
Оригинал: “https://dev.to/eliasnogueira/how-i-created-my-1f98”