SlideShare une entreprise Scribd logo
1  sur  51
Télécharger pour lire hors ligne
BEHAVIOR
           DRIVEN
           DEVELOPMENT
           ДЛЯ PHP ПРОЕКТОВ


@everzet
КТО Я
                symfony-разработчик
                С 2007 года
                СОЗДАТЕЛЬ
                BEHAT
                ВЕДУЩИЙ РАЗРАБОТЧИК

               DEV.BY
ПРОГРАММИСТ
С РОЖДЕНИЯ http://everzet.com
РАЗРАБОТКА
INSIDE-OUT
Тесты соединений
                                        Тесты двигателя




                              Тесты колес




                                            UNIT
Тесты электрики




                                            ТЕСТЫ
TDD


             +                =      ?
                                  качественный
unit-тесты       разработка       продукт
TDD


             +                =
                                  качественный-
unit-тесты       разработка       продукт
UNIT-ТЕСТЫ
ОТДЕЛЬНЫХ МОДУЛЕЙ
НЕ ГАРАНТИРУЮТ КАЧЕСТВО
РАБОТЫ СИСТЕМЫ В ЦЕЛОМ
РАЗРАБОТКА
OUTSIDE-IN
ВХОДНЫЕ/ВЫХОДНЫЕ

ДАННЫЕ




                   выходные
 входные           данные
 данные
RSpec

# bowling_spec.rb
require 'bowling'

describe Bowling, "#score" do
  it "returns 0 for all gutter game" do
    bowling = Bowling.new
    20.times { bowling.hit(0) }
    bowling.score.should == 0
  end
end
PHPSpec
<?php
require_once 'bowling.php'

class DescribeIndexController
    extends PHPSpec_Context_Zend
{
  public function itShouldDisplayHelloWorld()
  {
    $this->get(‘index’);
    $this->
      response()->
      should->
      match(‘/Hello World/’);
  }
}
Symfony Functional Test

<?php

$browser->get(‘/job/new’)->
  with(‘request’)->begin()->
    isParameter(‘module’, ‘job’)->
    isParameter(‘action’, ‘new’)->
  end()->

  click(‘Preview   your job’, array(‘job’ => array(
    ‘company’ =>   ‘Sensio Labs’,
    ‘url‘     =>   ‘http://sensio.com’,
    ‘logo‘    =>   ‘/uploads/jobs/sensio-labs.gif’,
  ));
BDD


                 unit-тесты

            +(      +         )=
                                   качественный
ПОВЕДЕНИЕ
                                   продукт
                 разработка
ТЕХНИКА
КОММУНИКАЦИЙ
ИДЕЯ
 # bowling_spec.rb
 require 'bowling'

 describe Bowling, "#score" do
   it "returns 0 for all gutter game" do
     bowling = Bowling.new
     20.times { bowling.hit(0) }
     bowling.score.should == 0
   end
 end
ИДЕЯ
 # bowling_spec.rb




            NO!
 require 'bowling'

 describe Bowling, "#score" do
   it "returns 0 for all gutter game" do
     bowling = Bowling.new
     20.times { bowling.hit(0) }
     bowling.score.should == 0
   end
 end
ИДЕЯ
 Хочу онлайн-боулинг
              с блэкджеком и...
 и он будет
              ПЛАТНЫМ
КОММУНИКАЦИИ

 Хочу кастомный
    Porsche
                    # bowling_spec.rb
                    require 'bowling'

                    describe Bowling, "#score" do
                      it "returns 0 for all gutter game" do
                        bowling = Bowling.new
                        20.times { bowling.hit(0) }
                        bowling.score.should == 0
                      end
                    end




                                                              разработка




                  написание спек
   идея
ФУНКЦИОНАЛ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
ФУНКЦИОНАЛ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
СЦЕНАРИИ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
ШАГИ


Feature: Addition
  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers

  Scenario: Add two numbers
    Given I have entered 10 into the calculator
    And I have entered 5 into the calculator
    When I press ‘plus’
    Then the result should be 15
БИБЛИОТЕКИ



ASSERTIONS   Test::Unit, RSpec

BROWSER      Webrat, Capybara, Selenium


RUNNER       Autotest, RStakeout, Watchr
ОПРЕДЕЛЕНИЯ

require 'calculator'

Given /I have entered (d+) into the calculator/ do
|n|
  @calc.push n.to_i
end

When /I press (w+)/ do |op|
  @result = @calc.send op
end

Then /the resoulr should be (.*)/ do |result|
  @result.should == result.to_f
end
ОПРЕДЕЛЕНИЯ

require 'calculator'

Given /I have entered (d+) into the calculator/ do
|n|
                ПИШУТСЯ на

               Ruby
  @calc.push n.to_i
end

When /I press (w+)/ do |op|
  @result = @calc.send op
end

Then /the resoulr should be (.*)/ do |result|
  @result.should == result.to_f
end
МИНУСЫ



 1. Не все PHP-разработчики знают/хотят знать Ruby
 2. Сложность при описании входных условий
 3. Невозможность использования PHP библиотек
 4. Скорость работы кросс-языкового решения
1. Написан с нуля на PHP5.3
2. Написан с применением Symfony Components
3. Старается быть Cucumber’ом с входными/выходными данными
4. Полностью нативное решение на PHP
5. Столь же быстр, что и Cucumber (проверено)
6. Поддерживает полную и17ю
7. Полностью расширяем и настраиваем
8. Поддерживает различные типы лоадеров
ФУНКЦИОНАЛ


Feature: Serve coffee
  In order to earn money
  Customers should be able to
  buy coffee at all times

  Scenario: Buy last coffee
    Given there are 1 coffees left in the machine
    And I have deposited 1$
    When I press the coffee button
    Then I should be served a coffee
ОПРЕДЕЛЕНИЯ


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {
       assertEquals(0, $world->return);
     }
   }
);
ОПРЕДЕЛЕНИЯ


<?php
ТИП ОПРЕДЕЛЕНИЯ
$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {
       assertEquals(0, $world->return);
     }
   }
);
ОПРЕДЕЛЕНИЯ


<?php
                  РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ
$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {
       assertEquals(0, $world->return);
     }
   }
);
ОПРЕДЕЛЕНИЯ


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     if (‘fail’ === $success) {
       assertNotEquals(0, $world->return);
     } else {                                CALLBACK
       assertEquals(0, $world->return);
     }
   }
);
ИСПОЛНЕНИЕ
Feature: Behat Console Runner
  Scenario: Run feature from CLI
    Given I have default Behat configuration
    When I call ‘behat -f progress’
    Then it should pass


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     ...
   }
);
ИСПОЛНЕНИЕ
Feature: Behat Console Runner
  Scenario: Run feature from CLI
    Given I have default Behat configuration
    When I call ‘behat -f progress’
    Then it should pass


<?php

$steps->Then(‘/^it should (fail|pass)$/’,
   function($world, $status) {
     // $status == ‘pass’
   }
);
СТАТУСЫ
<?php

$steps->Then(‘/^it should pass$/’, function($world) {
  return true;
});

$steps->Then(‘/^it passes$/’, function($world) {
  return false;
});

$steps->Then(‘/^it should fail$/’, function($world) {
  throw new Exception();
});

$steps->Then(‘/^it should pend$/’, function($world) {
  throw new EverzetBehatExceptionPending();
});
СТАТУСЫ
<?php

$steps->Then(‘/^it should pass$/’, function($world) {
  ...
});

$steps->Then(‘/^it should pass$/’, function($world) {
  // Will throw exception on definitions read
});

$steps->Then(‘/^it’s good$/’, function($world) {
  ...
});

$steps->Then(‘/^it’s w+$/’, function($world) {
  // Will throw exception on ‘it should pass call’
});
ПРИМЕР
ИСПОЛЬЗОВАНИЯ
УСТАНОВКА




$> pear channel-discover pear.everzet.com
$> pear install everzet/behat-beta
HOW MUCH IS THE FISH?

<?php # ./user.php

class User
{
  public function __construct($username, $age = 1)
  {
  }

    public function getName() {}

    public function getAge() {}
}
FEATURE

# ./features/user.feature
# language: ru

Функционал: Базовый Пользователь
  Чтобы работать с пользователями
  Как разработчик сайта
  Я хочу иметь доступ к
  пользовательской модели

  Сценарий: Создание пользователя
    Допустим у нас нет пользователей
    Если мы добавим пользователя ‘everzet’
    То у нас должно быть 1 пользователей
    И имя у первого пользователя ‘everzet’
GET SNIPPETS
ОПРЕДЕЛЕНИЯ
<?php # ./features/steps/user_steps.php

require_once ‘PHPUnit/Autoload.php’;
require_once ‘PHPUnit/Framework/Assert/Functions.php’;
require_once __DIR__ . ‘/../../user.php’;

$steps->

Допустим(‘/^у нас нет пользователей$/’, function($world) {
     $world->users = array();
})->

Если(‘/^мы добавим пользователя ’([^’]+)’$/’, function($world, $username) {
     $world->users[] = new User($username);
})->

To(‘/^у нас должно быть (d+) пользователей$/’, function($world, $count) {
     assertEquals($count, count($world->users));
})->

То(‘/^имя у первого пользователя ’([^’]+)’$/’, function($world, $username) {
    assertEquals($username, $world->users[0]->getName());
});
WATCH IT FAILS
РЕАЛИЗАЦИЯ
<?php # ./user.php

class User
{
  protected $name, $age;

    public function __construct($username, $age = 1)
    {
      $this->name = $username;
      $this->age = $age;
    }

    public function getName() { return $this->name; }

    public function getAge() { return $this->age; }
}
WATCH IT PASSES
TODO




1. CommonWebSteps
2. Annotated class step definitions and hooks
3. JUnit formatter
4. PDF/HTML formatter
5. Selenium integration
ССЫЛКИ
         ОФФИЦИАЛЬНЫЙ САЙТ
         http://everzet.com/Behat




         ОФФИЦИАЛЬНЫЙ РЕПОЗИТОРИЙ
         http://github.com/everzet/Behat




         ОФФИЦИАЛЬНАЯ GOOGLE GROUP
         http://groups.google.com/group/behat
ВОПРОСЫ?
CREDITS




http://www.flickr.com/photos/jasmic/279741827
http://www.flickr.com/photos/mulmatsherm/2312688473
http://www.flickr.com/photos/joshfassbind/4584323789
http://www.flickr.com/photos/bearuk/564788081
http://www.flickr.com/photos/jasmincormier/3511034253
http://www.flickr.com/photos/chuqui/4552338602

Contenu connexe

Tendances

CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest
 
Леонид Динерштейн - Разработка программ через тестирование поведения средства...
Леонид Динерштейн - Разработка программ через тестирование поведения средства...Леонид Динерштейн - Разработка программ через тестирование поведения средства...
Леонид Динерштейн - Разработка программ через тестирование поведения средства...
SQALab
 
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QAFest
 
М. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionМ. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с Codeception
Albina Tiupa
 
Pycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и DjangoPycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и Django
Ilya Shalyapin
 
Михаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionМихаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с Codeception
Albina Tiupa
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
ZFConf Conference
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
drupalconf
 

Tendances (19)

Saint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demoSaint Perl 2009: CGI::Ajax demo
Saint Perl 2009: CGI::Ajax demo
 
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
CodeFest 2012. Родионов А. — Тестирование Ruby (on Rails) приложений: стек, п...
 
Angular 2: Всех переиграл
Angular 2: Всех переигралAngular 2: Всех переиграл
Angular 2: Всех переиграл
 
Behat-trick: как мы внедряли BDD на наших проектах
Behat-trick: как мы внедряли BDD на наших проектахBehat-trick: как мы внедряли BDD на наших проектах
Behat-trick: как мы внедряли BDD на наших проектах
 
JS Fest 2018. Лилия Карпенко. Особенности создания IOS / Android Mobile Apps ...
JS Fest 2018. Лилия Карпенко. Особенности создания IOS / Android Mobile Apps ...JS Fest 2018. Лилия Карпенко. Особенности создания IOS / Android Mobile Apps ...
JS Fest 2018. Лилия Карпенко. Особенности создания IOS / Android Mobile Apps ...
 
Леонид Динерштейн - Разработка программ через тестирование поведения средства...
Леонид Динерштейн - Разработка программ через тестирование поведения средства...Леонид Динерштейн - Разработка программ через тестирование поведения средства...
Леонид Динерштейн - Разработка программ через тестирование поведения средства...
 
Основы доменной модели
Основы доменной моделиОсновы доменной модели
Основы доменной модели
 
Автоматизация UI тестирования под Windows и Windows Phone
Автоматизация UI тестирования под Windows и Windows PhoneАвтоматизация UI тестирования под Windows и Windows Phone
Автоматизация UI тестирования под Windows и Windows Phone
 
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
 
Сергей Татаринцев — bem-tools v1.0.0
Сергей Татаринцев — bem-tools v1.0.0Сергей Татаринцев — bem-tools v1.0.0
Сергей Татаринцев — bem-tools v1.0.0
 
Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16Что нового в Perl? 5.10 — 5.16
Что нового в Perl? 5.10 — 5.16
 
М. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с CodeceptionМ. Боднарчук Современное функциональное тестирование с Codeception
М. Боднарчук Современное функциональное тестирование с Codeception
 
Pycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и DjangoPycon Russia 2013 - Разработка через тестирование в Python и Django
Pycon Russia 2013 - Разработка через тестирование в Python и Django
 
Михаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с CodeceptionМихаил Боднарчук Современное функциональное тестирование с Codeception
Михаил Боднарчук Современное функциональное тестирование с Codeception
 
Cucumber on Kazan.rb
Cucumber on Kazan.rbCucumber on Kazan.rb
Cucumber on Kazan.rb
 
What’s New in PHP7?
What’s New in PHP7?What’s New in PHP7?
What’s New in PHP7?
 
ZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and DoctrineZFConf 2010: Zend Framework and Doctrine
ZFConf 2010: Zend Framework and Doctrine
 
Emmet - инструмент для веб-разработчика
Emmet - инструмент для веб-разработчикаEmmet - инструмент для веб-разработчика
Emmet - инструмент для веб-разработчика
 
Easy authcache 2 кеширование для pro родионов игорь
Easy authcache 2   кеширование для pro родионов игорьEasy authcache 2   кеширование для pro родионов игорь
Easy authcache 2 кеширование для pro родионов игорь
 

En vedette

En vedette (16)

BDD в PHP с Behat и Mink
BDD в PHP с Behat и MinkBDD в PHP с Behat и Mink
BDD в PHP с Behat и Mink
 
Testing with laravel
Testing with laravelTesting with laravel
Testing with laravel
 
Laravel Unit Testing
Laravel Unit TestingLaravel Unit Testing
Laravel Unit Testing
 
Modern Project Toolbox
Modern Project ToolboxModern Project Toolbox
Modern Project Toolbox
 
Being effective with legacy projects
Being effective with legacy projectsBeing effective with legacy projects
Being effective with legacy projects
 
Enabling agile devliery through enabling BDD in PHP projects
Enabling agile devliery through enabling BDD in PHP projectsEnabling agile devliery through enabling BDD in PHP projects
Enabling agile devliery through enabling BDD in PHP projects
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Modern Agile Project Toolbox
Modern Agile Project ToolboxModern Agile Project Toolbox
Modern Agile Project Toolbox
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Автоматизация для ленивых тестировщиков. Selenium + Python + Behave (BDD)
Автоматизация для ленивых тестировщиков. Selenium + Python + Behave (BDD)Автоматизация для ленивых тестировщиков. Selenium + Python + Behave (BDD)
Автоматизация для ленивых тестировщиков. Selenium + Python + Behave (BDD)
 
Bridging The Communication Gap, Fast
Bridging The Communication Gap, Fast Bridging The Communication Gap, Fast
Bridging The Communication Gap, Fast
 
Moving away from legacy code (AgileCymru)
Moving away from legacy code  (AgileCymru)Moving away from legacy code  (AgileCymru)
Moving away from legacy code (AgileCymru)
 
Taking back BDD
Taking back BDDTaking back BDD
Taking back BDD
 
Moving away from legacy code with BDD
Moving away from legacy code with BDDMoving away from legacy code with BDD
Moving away from legacy code with BDD
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 

Similaire à BDD для PHP проектов

Agile with cucumber or BDD with fun
Agile with cucumber or BDD with funAgile with cucumber or BDD with fun
Agile with cucumber or BDD with fun
Leonid Dinershtein
 
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлениюCodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
CodeFest
 
TestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщикаTestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщика
davertmik
 
Moscow Python Conf 2016. Почему 100% покрытие это плохо?
Moscow Python Conf 2016. Почему 100% покрытие это плохо?Moscow Python Conf 2016. Почему 100% покрытие это плохо?
Moscow Python Conf 2016. Почему 100% покрытие это плохо?
Ivan Tsyganov
 

Similaire à BDD для PHP проектов (20)

Mojolicious
MojoliciousMojolicious
Mojolicious
 
Agile with cucumber or BDD with fun
Agile with cucumber or BDD with funAgile with cucumber or BDD with fun
Agile with cucumber or BDD with fun
 
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлениюCodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
CodeFest 2012. Корсаков С. — Cucumber. Некоторые советы по приготовлению
 
automation is iOS development
automation is iOS developmentautomation is iOS development
automation is iOS development
 
Erlang tasty & useful stuff
Erlang tasty & useful stuffErlang tasty & useful stuff
Erlang tasty & useful stuff
 
TestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщикаTestGuy - эмулируем вашего тестировщика
TestGuy - эмулируем вашего тестировщика
 
Антипаттерны модульного тестирования (Донецкий кофе-и-код Сентябрь 2010)
Антипаттерны модульного тестирования (Донецкий кофе-и-код Сентябрь 2010)Антипаттерны модульного тестирования (Донецкий кофе-и-код Сентябрь 2010)
Антипаттерны модульного тестирования (Донецкий кофе-и-код Сентябрь 2010)
 
Plugin for plugin, or extending android new build system
Plugin for plugin, or extending android new build systemPlugin for plugin, or extending android new build system
Plugin for plugin, or extending android new build system
 
BDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehaveBDD girls Battle: Cucumber VS. JBehave
BDD girls Battle: Cucumber VS. JBehave
 
functional patterns - dotnetconf'11
functional patterns - dotnetconf'11functional patterns - dotnetconf'11
functional patterns - dotnetconf'11
 
Moscow Python Conf 2016. Почему 100% покрытие это плохо?
Moscow Python Conf 2016. Почему 100% покрытие это плохо?Moscow Python Conf 2016. Почему 100% покрытие это плохо?
Moscow Python Conf 2016. Почему 100% покрытие это плохо?
 
JavaScript не нужен, CoffeeScript - мимими
JavaScript не нужен, CoffeeScript - мимимиJavaScript не нужен, CoffeeScript - мимими
JavaScript не нужен, CoffeeScript - мимими
 
Тестируй это / Виктор Русакович (GP Solutions)
Тестируй это / Виктор Русакович (GP Solutions)Тестируй это / Виктор Русакович (GP Solutions)
Тестируй это / Виктор Русакович (GP Solutions)
 
Руководство по приготовлению бутербродов из Selenium
Руководство по приготовлению бутербродов из SeleniumРуководство по приготовлению бутербродов из Selenium
Руководство по приготовлению бутербродов из Selenium
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 
Chef
ChefChef
Chef
 
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVCАрхитектура кода нового 2ГИС Web API или куда мы дели MVC
Архитектура кода нового 2ГИС Web API или куда мы дели MVC
 
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
TypeScript: особенности разработки / Александр Майоров (Tutu.ru)
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать жить
 
“QA job interview: life hacks and scripts for success”
“QA job interview: life hacks and scripts for success”“QA job interview: life hacks and scripts for success”
“QA job interview: life hacks and scripts for success”
 

BDD для PHP проектов