Всю прошедшую неделю я потихоньку занимался развитием DelphiSpec. Хотя свободного времени у меня было не так уж и много, проделана большая работа и проект близок к той стадии, когда я без стеснения смогу объявить о выходе версии 1.0.

Давайте я вам вкратце расскажу о том, что теперь умеет DelphiSpec. Базовые вещи озвучены в предыдущем посте, обсудим, что появилось нового. А нового довольно много.

Во-первых, произошла по сути косметическая, но очень приятная модернизация — в классе содержащем step definitions простые шаги можно описывать без применения атрибутов.

В первом посте я показывал вам такой синтаксис:

    // пример сценария: "Given user ROOT exists"    
    [Given_('user (.*) exists')]
    procedure MyProcName(const Name: string);

Он отлично работает и сейчас, но теперь можно сделать еще проще — без атрибутов:

 
    // пример сценария: "Given user ROOT exists"
    procedure Given_user_name_exists(const Name: string);

То есть можно использовать имя самого метода для описания типа и синтаксиса шага. Выбирайте как удобнее.

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

 
    // пример сценария: "Given I have 3 apples"
    procedure Given_I_have_N_apples(N: Integer);

Можно передать даже массив:

 
    // пример сценария: "Given I have a list 1,2,3,4"
    procedure Given_I_have_a_list_Ns(Ns: TArray<Integer>);

И даже массив записей:

 
type   
  TUserInfo = record
    Name: string;
    Password: string;
    Id: Integer;
  end;

  // пример сценария
  // Given users exist:
  //  | id | name  | password |
  //  | 1  | Roman | pass1    |  
  //  | 2  | Other | pass2    |
  procedure Given_users_exist(Table: TArray<TUserInfo>);

Последний пример демонстрирует интересный тип данных Gherkin — data table. Обратите внимание, что такая таблица в метод-обработчик передается как массив обычных типизированных записей.

Всю работу с типами берет на себя DelphiSpec, вам об этом думать не придется. Библиотека может это делать благодаря магии RTTI. Не верьте, когда вам говорят, что волшебства не бывает :)

Еще один тип данных, который поддерживает Gherkin и теперь реализован в DelphiSpec — это «многострочные строки» в стиле Python. Такая строка обрамляется троекратными двойными кавычками сверху и снизу, а в метод-обработчик передается как обычный string:

 Given I have a blacklist:
   """
   m@mail.com
   123@mail.com
   """

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

Добавлена поддержка блока background. Этот блок позволяет описать контекст выполнения сценариев — он выполняется перед каждым сценарием.

Feature: Accounts

Background:
  Given users exist:
    | id | name  | password |
    | 1  | Roman | pass1    |  
    | 2  | Other | pass2    |

Scenario: Correct Login
  Given my name is "Roman"
    And my password is "pass1"
  When I login
  Then I have access to private messages

Scenario: Incorrect Login
  Given my name is "Roman"
    And my password is "pass2"
  When I login
  Then access denied

Также теперь можно описывать не только отдельные сценарии, но и более общие структуры сценариев:

Scenario Outline: Add two numbers
  Given I have entered <num1> in calculator
    And I have entered <num2> in calculator
  When I press Add
  Then the result should be <sum> on the screen
  
  Examples:
    | num1 | num2 | sum |
    |  1   |  2   |  3  | 
    |  4   |  5   |  9  |
    |  3   |  1   |  4  |

Такая структура будет развернута в несколько сценариев — по одному на каждую строку таблицы. В дереве DUnit подобная ситуация будет выглядеть вот так:

То есть создан не один тест «Add two numbers», а три. По одному для каждого случая.

Полный код примеров лежит вместе с библиотекой на github. Как я и обещал, DelphiSpec я не забрасываю и развиваю. Впереди мне предстоит тестирование и написание хотя бы краткой документации. А там уже и 1.0 не за горами :)

Связанные записи: