Рубрики
Uncategorized

Как построить пользовательскую интеграционную тестовую ремню в ржавчине

Я сталкиваюсь с проблемой, эффективно, используя тест груза в Fluvio для тестирования интеграции, давайте … Теги от ржавчины, дежопта, тестированием, учебником.

Я столкнулся с проблемой, эффективно использую Грузовый тест в Fluvio Для интеграции тестирования

Давайте поговорим о тестировании интеграции в ржавчине

Создавая тестирование интеграции для Fluvio, я столкнулся с проблемой. Организация и выполнение интеграционных испытаний с Грузовый тест становился неэффективным. Нам нужно было стандартизировать настройку тестовой среды.

В качестве одиночного разработчика вы можете применить односторонние настройки при прохождении тестов локально. Но если вы попытаетесь расширить эту стратегию для непрерывной интеграции, вы быстро найдете, что внесение изменений вручную становится обременительным. CI поощряет тестирование многих различных конфигураций, что означает успешный план CI, требует простого управления переменными ремня безопасности (A.k.a. Не обновляя переменные вручную для каждого необходимого теста).

Грузовый тест Просто не оборудован для обработки этого специализированного фокуса на настройке среды, или очистка/разрыва, необходимое после прохождения теста. При использовании Грузовый тест Эти решающие задачи могут возникнуть только вне жгута или внутри логики теста. Ни один из них не являются хорошими вариантами. Снаружи жгута не идеальна, потому что эти процессы в конечном итоге слишком отсоединены и трудно поддерживать. Аналогичным образом, включая настройку/разрыв в логике теста неуместно, потому что она создает умственную накладную головку для тестового писателя, а также может скрывать результаты испытаний.

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

Как по умолчанию работают грузовые тесты?

Существует различие между модульными тестами и тестами интеграции в Книга ржавчины Отказ Различие меньше о стратегии тестирования и далее о определении конвенций ржавчины для организации тестирования.

Основные моменты в том, что:

  • Ваши тесты аннотированы с #[контрольная работа]
  • libtest жгут перечисляет все ваши тесты (точка, которую мы пересмотрим позже более подробно)
  • libtest возвращает статус прохода/неудачи исполнения

Что мне нужно от тестирования интеграции?

Libtest не конкретно предлагает что-либо для поддержки узоров тестирования интеграции.

Настройка стандартной тестовой среды — особенно в сложной системе — необходима для управления ожидаемой поведением при изменении кода.

К сожалению, libtest не помогает с установкой или разрывом. Мне нужна возможность абстрагировать настройку и разрыв моей тестовой среды из тестового кода.

Эта задача будет выполнена в любом случае. Без поддержки жгута установка/разрыв будет выполнена с помощью внешних сценариев оболочков или заполнение процесса настроек/разрыва в каждом тесте на интеграцию … (Никто не представляет удовольствие).

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

Где мы начнем с пользовательскими тестами?

По умолчанию Libtest будет скомпилировать каждый из ваших # [тест] помеченные функции в свои бинарные ящики (с собственным основным () ) и выполняют его как часть теста. Но мы собираемся создать все наши тесты интеграции в один ящик. Это рекомендуется для ускорения времени компиляции ([ 1 ], [ 2 ])

Сначала мы собираемся создать интеграционную тестовую каталог в корне в Crate, где мы собираемся создать нашу интеграционную тестовую тест сфокусированным двоичным.

$ mkdir integration
$ touch integration/main.rs

# Then create a main() function in main.rs

В вашем Cargo.toml вы хотите добавить

# Cargo.toml

# We'll revisit the `inventory` crate later in the post
[dev-dependencies]
inventory = "0.1"

[[test]]
name = "integration"
path = "integration/main.rs"
harness = false

Это говорит о грузовом тесте не использовать libtest при запуске Интеграция контрольная работа.

Когда мы бежим Грузовая тестовая интеграция , какой груз будет скомпилировать Интеграция/Main.rs и выполнить это так же, как Грузовой пробег . Это все жгут от груз перспектива.

Добавить шаги настроек и разрыва

Далее мы будем заложить основу для нашего образца тестирования. Мы создадим 2 функции, Настройка () и Обзор () и добавьте их к нашему Главная () (с зарезервированным пространством между нашими будущими тестами, которые будут называться).

// main.rs

fn setup() {
   println!("Setup")
}

fn teardown() {
   println!("Teardown")
}
fn main() {
   // Setup test environment
   setup();

   // TODO: Run the test

   // Teardown test environment
   teardown();
}

Соберите все тесты интеграции

Чтобы выполнить свою работу, наш тестовый бегун должен создать список всех тестовых функций. Первоначально я думал, что будет простой способ сделать это, используя libtest ‘s # [тест] атрибут.

Я выкопал в соответствующие области libtest и Грузовый тест и Rustc Macros Код, но длинная (грустная) история коротко, нет простого способа повторно использовать libtest с целью тестовой коллекции.

Если это удивляет вас, то ты как я. Я надеялся использовать функциональность тестового сбора из # [тест] , но не было понятно, как я мог бы сделать это. Моя умственная модель для того, как Грузовый тест Работы нуждались в обновлении.

Теперь, когда мы сняли вариант использования libtest, поэтому дает вам 2 практических варианта для сбора испытаний:

  1. Вручную модифицировать Интеграция/Main.rs и добавьте свой тест между настройкой и разрывом

    • Быстрое и простое решение, если у вас небольшой набор тестов
    • Эта опция требует, чтобы мы добавили новые тесты в этот список, что может быть подвержено ошибкам и утомительно, когда мы расти.
  2. Построить тестовый коллектор. Мы генерируем внешний тестовый каталог и измените Интеграция/Main.rs выполнять тесты из каталога.

    • Это долгосрочное решение, которое мы будем покрывать до конца поста.

Создание тестового коллектора

Для этого тестового коллектора мы будем использовать ящик. инвентарь CRATE — это система реестра плагинов. Мы будем использовать его для всех тяжелых лифтингов в нашей структуре тестирования, что означает, что мы будем относиться к нашим тестам в качестве плагинов.

В нашем main.rs Давайте объявим новый модуль тесты , где мы можем организовать все тесты интеграции.

// main.rs

+ pub mod tests;

fn setup() {
   println!("Setup")
}

fn teardown() {
   println!("Teardown")
}
fn main() {
   // Setup test environment
   setup();

   // TODO: Run the test

   // Teardown test environment
   teardown();
}

В нашем новом модуле мы начнем с создания структуры для представления одного теста для реестра плагина.

// tests/mod.rs

#[derive(Debug)]
pub struct IntegrationTest {
   pub name: &'static str,
   pub test_fn: fn(),
}

inventory::collect!(IntegrationTest);

В этом примере наша структура ИнтеграцияТест имеет 2 поля.

  • название это читаемое человеком именем, которое можно использовать в качестве ключа для выбора теста.
  • test_fn Это указатель на функцию, подпись которой несынчна, не требует ARGS и ничего не возвращает.

Примечание: Вы можете использовать функции, которые принимают args и возвращает вещи.

Например:

pub test_fn: fn(String) -> Result<(), ()>,

Тогда мы называем Инвентаризация:: Соберите! () Макрос для создания реестра плагина. Когда мы пишем наши тесты, мы добавим к реестру плагина. Больше на этом следующем.

Добавление новых тестов на реестр плагина

Мы собираемся добавить новый базовый тест в реестр плагина. Начните с добавления нового подмодуля под названием Базовый в модуле тестов.

// tests/mod.rs

pub mod basic;

В Базовый Модуль, мы пишем наш базовый тест basic_test ()

// tests/basic.rs

use super::IntegrationTest;

fn basic_test() {
   println!("Running basic test")
}

inventory::submit!(IntegrationTest {
   name: "basic",
   test_fn: basic_test
});

Мы будем использовать Инвентаризация:: Отправить! () Чтобы зарегистрировать наш новый тест с ИнтеграцияТест структура, которую мы определили ранее.

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

test_fn принимает имя нашей тестовой функции. Он имеет такую же функцию подписи, как мы определили.

Запуск тестов из реестра

Мы закончим этот пример, запустив все наши зарегистрированные тесты

// main.rs

pub mod tests;
+ use tests::IntegrationTest;

fn setup() {
   println!("Setup")
}

fn teardown() {
   println!("Teardown")
}
fn main() {
   setup();

-   // TODO: Run the test
+   // Run the tests
+   for t in inventory::iter:: {
+       (t.test_fn)()
+   }

   teardown();
}
$ cargo test integration
   Compiling blog-post-example v0.1.0 (/home/telant/Documents/blog-post-example)
    Finished test [unoptimized + debuginfo] target(s) in 0.21s
    Running target/debug/deps/blog_post_example-e042d787684bb333

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

    Running target/debug/deps/integration-7ed2452642c6f3b6

Setup
Running basic test
Teardown

Советы по расширению примера

Примером запускается все зарегистрированные тесты. Но вот некоторые полезные, требующие, если вы хотите простираться еще дальше. Например, добавление CLI, если вы хотите выбрать отдельные тесты. Или предоставить параметры для настройки поведения на установку или разрыва.

impl IntegrationTest {
   pub fn all_test_names() -> Vec<&'static str> {
       inventory::iter::
           .into_iter()
           .map(|x| x.name)
           .collect::>()
   }

   pub fn from_name>(test_name: S) -> Option<&'static IntegrationTest> {
       inventory::iter::
           .into_iter()
           .find(|t| t.name == test_name.as_ref())
   }
}

Если вы хотите увидеть больше этих идей, продлен еще дальше, проверьте Интеграция Fluvio Test Runner Отказ

Мы используем CLI для настройки настройки, обрабатывать Async Testing, и мы используем [атрибут MACRO] для сбора тестов.

[Атрибут макрос]: https://github.com/infinyon/fluvio/blob/master/tests/runner/src/fluvio-integration-derive/src/lib.rs

Вывод

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

Если мы хотим избежать восстановления колеса, нам нужна стабильная поддержка от libtest Или более примеры того, как выполнять коллекцию тестов и шаблонов для настроек, тестирования и разрыва рабочих процессов.

Если вы сделали это далеко, спасибо за следующее вместе со мной! Я написал это, потому что я не смог найти руководство, чтобы сделать это, прежде чем пытаться сделать это сам, и, зная эти вещи заранее, сделали бы намного быстрее. Надеюсь, другие найдут мой опыт полезным.

Оригинал: «https://dev.to/tjtelan/how-to-build-a-custom-integration-test-harness-in-rust-7n7»