среда, 21 мая 2014 г.

Тестируем калькулятор №5. Тесты через "новую архитектуру"

Здравствуйте читатели.
Александр любезно предоставил мне  "площадку" для понимания TDD.
Постижение написания кода через тестирование под руководством опытного наставника... Что может быть приятней :).

Небольшая преамбула:
18 февраля Всеволод Леонов предложил Александру показать каким образом приложение которое не задумывалось для тестирования превратить в full-testable system.
Приложением для примера был выбран обычный калькулятор:
Проект был банален до невозможности, 4 кнопки 3 Edit.

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

Первым делом добавляем к приложению тесты(DUnit), детали описаны здесь.
Следующим шагом Александр "посещает форму, присваивает 2 значения Едитам и проверяет кнопку Плюс".
Третий этап означал расширение тестов от одной операции(Плюс) до покрытия всех кнопок. Александр при этом выделил абстрактный класс - TOperationTest. В комментариях к этому посту развернулась довольно интересная дискуссия по поводу выделения абстрактного класса, зачем и почему читатели узнают из будущих постов :)
В четвертом посте Александр выделил класс "бизнес-логики" -  TCalculator, в котором находятся функции для расчета всех операций калькулятора.

Ну а сегодня мы обсудим тестирование логики нашего приложения.
После изменений архитектуры мы можем протестиорвать непосредственно "логику приложения". Поэтому. Самый простой способ сделать это сейчас это написать класс TCalculatorOperation отнаследованный от TTestCase и проверить все операции. Я правда ещё и проверил ошибочность выполнения в одной из операций. Но я думаю что если читателям будет интересно то эту тему мы обсудим в комментариях.
Собственно код:
unit CalculatorOperationTest;

interface

uses
  TestFrameWork,
  Calculator
  ;

 type
  TCalculatorOperationTest = class(TTestCase)
   published
    procedure LogicTestDiv;
    procedure LogicTestMul;
    procedure LogicTestAdd;
    procedure LogicTestSub;
    procedure LogicTestSubError;
  end;//TCalculatorOperationTest

implementation

  uses
   SysUtils;

const
 cA = '5';
 cB = '10';
{ TCalculatorOperationTest }

procedure TCalculatorOperationTest.LogicTestDiv;
var
  x1, x2  : string;
  result : Single;
begin
  x1:= cA;
  x2:= cB;
  result := StrToFloat(TCalculator.Divide(x2, x1));
  CheckTrue(2 = result);
end;

procedure TCalculatorOperationTest.LogicTestSub;
var
  x1, x2  : string;
  result : Single;
begin
  x1:= cA;
  x2:= cB;
  result := StrToFloat(TCalculator.Sub(x2, x1));
  CheckTrue(5 = result);

end;

procedure TCalculatorOperationTest.LogicTestSubError;
var
  x1, x2  : string;
  result : Single;
begin
  x1:= cA;
  x2:= cB;
  result := StrToFloat(TCalculator.Sub(x2, x1));
  CheckFalse(7 = result);
end;

procedure TCalculatorOperationTest.LogicTestMul;
var
  x1, x2  : string;
  result : Single;
begin
  x1:= cA;
  x2:= cB;
  result := StrToFloat(TCalculator.Mul(x2, x1));
  CheckTrue(50 = result);
end;

procedure TCalculatorOperationTest.LogicTestAdd;
var
  x1, x2  : string;
  result : Single;
begin
  x1:= cA;
  x2:= cB;
  result := StrToFloat(TCalculator.Add(x2, x1));
  CheckTrue(15 = result);
end;

initialization
 TestFramework.RegisterTest(TCalculatorOperationTest.Suite);
end.

Таким образом мы ушли от "тестирования GUI" к тестированию "бизнес логики".


upd1. Залил исходнки на BitBucket.

9 комментариев:

  1. Ответы
    1. http://ru.wikipedia.org/wiki/KISS_(%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF)

      Удалить
    2. лямбды Вы даже может и правы.
      только "бежите впереди паровоза"
      и пихать их везде где возможно, не знаю...

      http://habrahabr.ru/post/153225/

      p.s.
      В статье я писал "Самый простой способ". Или Вы по диагонали читаете ?

      Удалить
    3. >Give me example, Father...
      Старый пример на хаскеле: http://pastebin.com/RwkA2CTA
      (на дельфи не пишу, но и лямбды и функции первого класса современный дельфи умеет)

      >KISS
      А что может быть проще одной функции?

      >В статье я писал "Самый простой способ". Или Вы по диагонали читаете ?
      с лямбдами проще же. Не стоит забывать про принцип DRY. =)

      Удалить
    4. "Старый пример на хаскеле: http://pastebin.com/RwkA2CTA"

      -- точно "по-диагонали" читаете...

      Удалить
    5. "с лямбдами проще же"

      -- в КАКОМ месте и ЧТО упрощать? Пальцем ткните, нам, недоумкам.

      Удалить
    6. "DRY"

      -- в КАКОМ месте примера было "повторение себя" или "по-русски" говоря "техника Cut'N'Paste"??

      Можно увидеть?

      Удалить
  2. > в КАКОМ месте примера было "повторение себя" или "по-русски" говоря "техника Cut'N'Paste"??

    сравните описанные процедуры тестирования.

    >точно "по-диагонали" читаете...

    поясните

    ОтветитьУдалить