Тестирование -
философия современного разработчика

TDD

BDD
ATDD
Unit Tests
Functional Tests
Acceptance Tests

White Box vs Black Box
Unit Tests / Модульные Тесты
Arrange - подготовка
Act - выполнение
Assert - проверка
Пример
class КалькулятораТест {
умножениеНаНольДолжноВернутьНоль() {
// Калькулятор, который тестируется
калькулятор = new Калькулятор();
// проверки
сравнитьРавенство(
0,
калькулятор.умножить(10, 0),
"10 x 0 должно вернтуть 0"
);
сравнитьРавенство(
0,
калькулятор.умножить(0, 10),
"0 x 10 должно вернтуть 0"
);
}
}GWT
-
Given - начальное состояние системы
-
When - действия пользователя
-
Then - результат
Functional Tests / Функциональные Тесты
<?php
$I->amOnPage('/');
$I->click('Login');
$I->fillField('Username', 'Miles');
$I->fillField('Password', 'Davis');
$I->click('Enter');
$I->see('Hello, Miles', 'h1');
Acceptance Tests / Приемочные Тесты
Feature: Базовая Арифметика
Background: Калькулятор
Дан калькулятор, который я только что включил
Scenario: Сложение
Когда я складываю 4 и 5
Тогда результат 9
Scenario: Еще одно сложение
Когда я складываю 4 и 7
Тогда результат 11Integration Tests / Интеграционные Тесты
-
Acceptance
-
Functional
-
Unit
ATDD
BDD
TDD
=
Methodology
TDD

Тест падает
Тест проходит
Рефакторим
BDD
Спецификация
Разработка
Коммуникация
ATDD
Разработка Тестов
Разработка
Спецификация
BDD vs ATDD
T это ключ
Acceptance
Functional
Integration
Unit

Не Писать Тесты


Не можем мы
их продать!!!!!
Писать Тесты

class Пользователь расширяет ActiveRecord {
имя;
фамилия;
}
class ПользователяТест {
@Test
сохранитьПользователя() {
пользователь = new Пользователь();
пользователь.имя = "Иван";
пользователь.фамилия = "Иванов";
сравнитьИстинность(
пользователь.сохранить(),
"пользователь должен сохраниться"
);
}
}Псевдокод
class Пользователь extends ActiveRecord {
имя;
фамилия;
статус;
являетсяЛиАктивным() {
вернуть статус == 1;
}
}
class ПользователяТест {
@Test
сохранитьПользователя() {
пользователь = Пользователь.найтиПоНомеру(1);
сравнитьИстинность(
пользователь.являетсяЛиАктивным(),
"пользователь должен быть активным"
);
}
}Писать Избыточные Тесты
Писать "Для Галочки"

Насяльника
Я сделаль!
тестироватьСделать() {
модель = new Пользователь();
сравнитьИстинность(модель.сделать());
сравнитьЛожь(модель.сделать());
}Псевдокод
Писать Тесты "Для Себя"

Отсутствие Информативности
public function testSaveLoad()
{
static::$time = static::$filemtime = \time();
$this->prepareData();
$items = $this->auth->items;
$children = $this->auth->children;
$assignments = $this->auth->assignments;
$rules = $this->auth->rules;
$this->auth->save();
$this->auth = $this->createManager();
$this->auth->load();
$this->assertEquals($items, $this->auth->items);
$this->assertEquals($children, $this->auth->children);
$this->assertEquals($assignments, $this->auth->assignments);
$this->assertEquals($rules, $this->auth->rules);
}Yii2 Rocks
public function testInitControllerNamePluralization() {
$suites = $this->getTestsForControllerNamePluralization();
foreach ($suites as $i => $suite) {
list($name, $tests) = $suite;
foreach ($tests as $j => $test) {
list($config, $expected) = $test;
$rule = new UrlRule($config);
$this->assertEquals($expected, $rule->controller, "Test#$i-$j: $name");
}
}
}
public function testRenderWithCustomInputId() {
$expectedValue = <<<EOD
<div class="form-group field-custom-input-id">
<label class="control-label" for="custom-input-id">Attribute Name</label>
<input type="text" id="custom-input-id" class="form-control" name="ActiveFieldTestModel[{$this->attributeName}]">
<div class="hint-block">Hint for attributeName attribute</div>
<div class="help-block"></div>
</div>
EOD;
$this->activeField->inputOptions['id'] = 'custom-input-id';
$actualValue = $this->activeField->render();
$this->assertEqualsWithoutLE($expectedValue, $actualValue);
}

При Ошибке Нас Обрадуют Сообщения
Code Specs
Спешит На Помощь

class IncomeCalculatorTest extends Specification {
private const ОЖИДАЕМЫй_НАЛОГ_ПЕРВОГО_УРОВНЯ = 4500;
private const ОЖИДАЕМЫй_НАЛОГ_ВТОРОГО_УРОВНЯ = 7200;
private const ОЖИДАЕМЫй_НАЛОГ_ТРЕТЬЕГО_УРОВНЯ = 30000;
private const ДОХОД_ПОСЛЕ_ВЧЕТА_НАЛОГА_ПЕРВОГО_УРОВНЯ = 300000;
/**
* @test
*/
public function calculateTaxSpec() {
$clientsPayments = []; // ЗАГОТОВКА ПЛАЖЕТЕЙ
$hoursSpentWorking = 160; // ЧАСЫ РАБОТЫ
$service = new IncomeCalculator($clientsPayments, $hoursSpentWorking);
$I = $this->tester;
$I->describe('расчет налога на доход');
$I->expectThat('для дохода менее 50 000 калькулятор использует ставку 10%');
$I->lookAt('налог первого уровня');
$I->seeNumber($service->calculateTax())
->isNotEmpty()
->isEqualTo(self::ОЖИДАЕМЫй_НАЛОГ_ПЕРВОГО_УРОВНЯ );
}
}Информативность Отчета Об Ошибках

Вопросы?
Тестирование - философия современного разработчика [RU-simplified]
By Dima Kolodko
Тестирование - философия современного разработчика [RU-simplified]
- 434