Forger

Назначение

Forger разработан, чтобы упростить написание тестового кода в части создания автоматически сгенерированных объектов/примитивов, что позволяет разработчику сосредоточиться на действительно важных вещах, а не изобретать временные подделки. Задача Forger - сэкономить время и не захламлять код объявлениями неважных для теста данных, тем самым облегчив как написание, так и чтение тестов.

Рассмотрим небольшой пример:

// interface Student {name: string, age: number}
describe('student.service', () => {
   it('save success', () => {
      const student = Forger.create<Student>();
      //
      const result = studentService.save(student);
      //
      console.log(student) // { name: 'I8SE1ou3ZD', age: 345 }
      expect(result).toBeTruthy();
   })
});

Смысл этого примитивного теста в том, чтобы проверить результат ответа определенного сервиса. Для нас совершенно не важно, какие конкретно данные будут передаваться внутри Student. В отсутствие Forger разработчик был бы вынужден вручную написать некую заглушку, что к тому же создало бы у читателя неуверенность в важности этих данных. С Forger тест содержит только те данные, которые действительно важны для него.

Шпаргалка

Генерация строк

Пример без настроек

   const text = Forger.create<string>();
   // &3rg5T/]0l

Произвольная длина строки

Длина строк по умолчанию равна 10 символам, но вы можете установить любое значение.

   const text = Forger.create<string>({stringLength: 20});
   // w!;a0/mVbsqS5rTOc|G-

Специальные символы

По умолчанию в генерируемую строку включаются специальные символы (~!@#$%^&*()_+-=[]{}|;:'",./<>?), но вы можете запретить это

   const text = Forger.create<string>({stringSpecial: false});
   // fXaM8rCib3

Числа

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

   const text = Forger.create<string>({stringNumbers: false});
   // !(}I@gGMUB

Строчные буквы

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

   const text = Forger.create<string>({stringLowCase: false});
   // ?7CJ0\35-"

Верхний регистр

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

   const text = Forger.create<string>({stringLowCase: false});
   // %0g35cu19h

Генерация чисел

Максимальное значение

По умолчанию максимальное значение равно 1000, но вы можете установить любое желаемое значение.

   const text = Forger.create<number>({numberMax: 10});
   // 7

Минимальное значение

По умолчанию минимальное значение равно 1, но вы можете установить любое желаемое значение.

   const text = Forger.create<number>({numberMin: 100});
   // 722

Дробные числа

По умолчанию числа не являются дробными, но вы можете изменить это

   const text = Forger.create<number>({numberFloat: true});
   // 195.84581602928762

Генерация даты

Минимальной дата

По умолчанию минимальная дата — 01.01.2000, но вы можете установить любое значение.

   const text = Forger.create<Date>({dateMin: new Date(2022,0,1)});
   // 2340-09-03T08:53:21.477Z

Максимальная дата

По умолчанию максимальная дата — 01.01.4000, но вы можете установить любое значение.

   const text = Forger.create<Date>({dateMax: new Date(2020,0,1)});
   // 2012-02-01T02:53:27.420Z

Генерация массивов

По умолчанию длина массивов равна 3, но вы можете установить любое значение.

   const text = Forger.create<number[]>({arrayLength: 6});
   // [ 543, 304, 502, 383, 734, 77 ]

Циклические зависимости

По умолчанию Forger разрешает один уровень ЦЗ, давайте рассмотрим пример:

   interface Test { child: InnerTest }
   interface InnerTest { parent: Test }
   const test = Forger.create<Test>();
   // {child: {parent: {child: {parent: null}}}}

Как видите, экземпляры повторяются один раз. Вы можете изменить это поведение, установив соответствующий уровень ЦЗ.

   const test = Forger.create<Test>({}, 2); // Разрешено два повтора в иехрархии

или запретить повторы

   const test = Forger.create<Test>({}, 0);

Комбинация настроек

create() принимает объект типа SpoofSettings и вы можете комбинировать настройки по своему усмотрению.

Инсталляция

Этот раздел будет обновляться, как только у меня будет время, но если у вас возникнут трудности с установкой и использованием Forger, не стесняйтесь писать мне.

К сожалению, определение типов в typescript не так просто, как хотелось бы; поэтому установка требует немного больше действий, чем просто npm install... Приступим.

Jest

   npm install @artstesh/forger -D

Надеюсь, у вас уже установлен Jest, поэтому нам нужно немного изменить jest.config.js:

   module.exports = {
     preset: 'ts-jest',
     globals: {
       'ts-jest': {
         astTransformers: {
           before: ['@artstesh/forger']
         }
       }
     }
   };

Вот и все! Не так уж много работы) С этого момента вы уже можете писать свои тесты с помощью Jest и Forger.

Angular

На данный момент этот подход работает для Angular 12+.

Angular вообще не любит трансформации кода, так что инструкция будет длиннее, чем для Jest. На данный момент я предполагаю использовать ng-custom-transformers, но в будущих выпусках я собираюсь упростить установку. Давайте начнем

  1. npm i @artstesh/forger @angular-builders/custom-webpack ng-custom-transformers@1.0.2 -D
  2. Создайте файл test-mod.webpack.config.js (или любое другое имя) в корне. Вы можете поместить его куда угодно, но будьте осторожны на шаге 3 и внимательно посмотрите на path.
   const {AngularCustomTransformers} = require("ng-custom-transformers");   
   module.exports = (config, options, targetOptions) => AngularCustomTransformers.modifyConfig(config);
  1. В angular.json измените раздел test
{
    "architect": {
        "build": {
            "test": "@angular-builders/custom-webpack:karma",
            "options": {
                "customWebpackConfig": {
                    "path": "./test-mod.webpack.config.js"
                }
            }
        }
    }
}
  1. В tsconfig.spec.json добавьте раздел plugins.
{
  "compilerOptions": {
    "plugins": [
      { "transform": "@artstesh/forger/lib/utils/transformer" }
    ]
  }
}

Вот и все.

Ограничения и будущие функции

Generic types

На данный момент Forger не поддерживает generic (ISomeInterface<T>). Я собираюсь добавить эту функциональность в ближайший релиз.

Подделка методов

Я не гарантирую подделку методов. Forger, вероятно, будет корректно работать с интерфейсами, но классы здесь не приветствуются) Если вы хотите подделывать сервисы, я рекомендую использовать что-то вроде ts-mockito. Возможно, я реализую соответствующие механизмы, но я не думаю, что это очень важно в данный момент.

Помощь

Если вы столкнулись с проблемами при использовании Forger, пишите мне через Feedback, я постараюсь ответить максимально оперативно.

Лицензия

Этот проект находится под лицензией MIT