Библиотека модульного тестирования unittest - выполнение определенного набора тестов

В любой современной методологии разработки ПО тестирование является неотъемлемой частью процесса, а значимость его написания не ниже значимости написания кода. Для большинства популярных языков программирования высокого уровня существуют инструменты и библиотеки модульного тестировани, язык dart не является исключеним - dart sdk комплектуется библиотекой для автомтического тестирования приложений - unittest.

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

  • Чтобы запустить только один тест, необходимо, использовать функцию solo_test(), просто заменив обычный вызов теста test() на solo_test(), и тогда выполнется только этот определенный тест, из всего набора.
  • Другой способ для выборочного запуска тестов, состоит в использовании функции filterTests(), которая принимает в качестве аргумента строку (String) или регулярное выражение (RegExp), а потом последовательно сравнивается названия тестов со этой строкой или регулярным выражением, и если обнаруживается соответсвие, то тест исполняется.

Выборочный запуск тестов с помощью функции filterTests()

Рассмотрим более детально второй случай, здесь недостаточно просто вызывать функцию filterTests() - во-первых, перед запуском filterTests() - необходимо отключить автовыполнение тестов в приложении, что можно легко сделать с помощью класса Configuration, и опции autoStart. А во-вторых, после объявления всех тестов, нужно вызвать filterTests() для фильтрации тестов и runTests() для запуска:

// объявляем новый класс для конфигурации, в котором отключен автозапуск тестов
class FilterTests extends Configuration {
  get autoStart => false;
}

void main() {
  // инициализируем нашу новую конфигурацию
  configure(new FilterTests());
  ensureInitialized();  

  ...
  // объявляем тесты
  ...

  // фильтруем
  filterTests('ключевое слово');
  
  // запускаем отобранные тесты
  runTests();
}

 

Полностью пример будет выглядить таким образом:

// подключаем библиотеку для тестирования к нашему проекту
import "package:unittest/unittest.dart";

// объявляем конфигурацию
class FilterTests extends Configuration {
  // отключаем автозапуск
  get autoStart => false;
}

void main() {
  // инициализируем конфигурацию без автозапуска тестов
  configure(new FilterTests());
  ensureInitialized();

  // тест 1
  test("simple test 1", () {
    isTrue(true);
  }); 

  // тест 2
  test("simple test 2", () {
    isFalse(false);
  });

  // тест 3
  test("test fail", () {
    fail("тест провалился");
  });
  
  // группа тестов
  group("simple group", () {
    test("subtest1", (){
      expect('unit', equals('test'));
    }); 

    test("subtest2", (){
      expect('test', equals('unit'));
    });
  });
  
  // тест с исключением
  test("complex exception", () {
    Expect.throws(() { throw new ArgumentError(); }, (e) => e is ArgumentError);
  });

  // с помощью данного вызова выполнятся первые три теста, потому что в их названиях встречается подстрока "test", а так же
  // тесты из группы "simple group"
  filterTests('test');
  
  // выберем только последний тест
  filterTests('complex');
  
  // выберем тесты из группы "simple group"
  filterTests('group');

  // запускаем выполнение тестов
  runTests();
}

Стоит отметить, что для корректного запуска, в данном примере, стоит закомментировать все вызовы filterTests кроме одного, в противном случае, будут выполнятся только те тесты, которые одновременно удволетворяют сразу всем условиям filterTests().

Выборочный запуск тестов с помощью аргументов командной строки

Чтобы сделать запуск тестов еще более удобным, можно расширить функциональность нашего приложения таким образом, чтобы передавать аргумент в функцию filterTests() с помощью коммандной строки. Тогда мы сможем запускать необходимый набор тестов без изменения исходного кода и перекомпиляцией программы.

// подключаем библиотеку для тестирования к нашему проекту
import "package:unittest/unittest.dart";
// подключаем библиотеку для работы с аргументами коммандной строки
import "package:args/args.dart";

// объявляем конфигурацию
class FilterTests extends Configuration {
  // отключаем автозапуск
  get autoStart => false;
}

void main() {
  // инициализируем конфигурацию без автозапуска тестов
  configure(new FilterTests());
  ensureInitialized();
  
  // объявлем парсер аргументов командной строки
  ArgParser argParser = new ArgParser();
  Options options = new Options();
  
  // разбираем аргументы коммандной строки
  ArgResults results = argParser.parse(options.arguments);
  // и передаем результат в массив строк
  List args = results.rest;

  // тест 1
  test("simple test 1", () {
    isTrue(true);
  }); 

  // тест 2
  test("simple test 2", () {
    isFalse(false);
  });

  // тест 3
  test("test fail", () {
    fail("тест провалился");
  });
  
  // группа тестов
  group("simple group", () {
    test("subtest1", (){
      expect('unit', equals('test'));
    }); 

    test("subtest2", (){
      expect('test', equals('unit'));
    });
  });
  
  // тест с исключением
  test("complex exception", () {
    Expect.throws(() { throw new ArgumentError(); }, (e) => e is ArgumentError);
  });

  // в случае, если переданы аргументы в командной строке, выбираем необходимы тесты
  if (!args.isEmpty) {
    filterTests(args[0]);
  }
  
  // запускаем выполнение тестов
  runTests();
}

Теперь запуск тестов будет осуществлятся с помощью командной строки:

dart tests.dart [ключевое слово или имя теста]

// выполним тесты 1, 2 и все тесты из группы "simple group"
dart tests.dart simple

// выполним тест с исключением
dart tests.dart exception

// выполнятся все тесты
dart tests.dart

На основе стать из блога Shailen Tuli's blog, "Running Only Some of Your Tests" http://shailen.github.com/blog/2012/12/07/running-only-some-of-your-tests/