Тестирование -

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

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
    Тогда результат 11

Integration 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