Codeception - тестируем по-человечески

Михаил Боднарчук

Codeception - тестируем по-человечески

Михаил Боднарчук

Oбо мне

me
  1. Веб разработчик из Киева
  2. Пишу на PHP, Ruby, CoffeeScript
  3. Разрабатываю open-source продукты: Codeception, Robo, AspectMock
  4. По выходным летаю на пепелаце (сломался)

О тестировании

  1. Стоит ли вообще тестировать?
  2. Что это за страшные слова: TDD, BDD, Test Doubles, Story BDD, Spec BDD, Stubs, Mocks, Spies, Fakes, Fixtures?
  3. С чего начать тестирование?

Начинают писать тесты

  1. Когда после деплоя ничего не работает
  2. Когда после мерджа всё поломалось
  3. Когда надоело проверять API вручную
  4. Когда постоянно приходится всё проверять вручную

Подходы к тестированию

  1. Прагаматический подход - Test After
  2. TDD - Test First (Is TDD Dead?)
  3. BDD - улучшенный TDD
    • Spec BDD - внутренние спецификации
    • Story BDD - требования заказчика

Best Practices

  1. Тест состоит из условия, действия, проверки
  2. Отделить дополнительный код от теста
  3. Отделить конфигурацию от теста
  4. Делать тесты читабельными (и компактными)

С чего начать тестирование?

O Codeception

  1. Современный фреймворк для тестирования в PHP
  2. Прост в установке, продвигает best practices тестирования
  3. Поддерживает приемочные, функциональные и юнит тесты
  4. Более 20 модулей, включая Selenium, Symfony, Yii, Laravel...
  5. Основан на PHPUnit, Symfony Components, Guzzle
  6. https://codeception.com

Немножко истории...

Пирамида тестирования

pyramid

✓ Приемочные тесты

Функциональные тесты

Юнит тесты

Простой тест

					$I = new AcceptanceTester($scenario);
					$I->amOnPage('/login');
					$I->fillField('email','[email protected]');
					$I->fillField('password','mysecurepassword');
					$I->click('#loginForm input[type=submit]');
					$I->seeCurrentUrlIs('/dashboard');
					$I->see('Welcome back','.notice');
			
		

Читабельные тесты

мысленно уберем все спецсимволы...
			
				I = new AcceptanceTester
				I amOnPage '/login'
				I fillField 'email','[email protected]'
				I fillField 'password','mysecurepassword'
				I click '#loginForm input[type=submit]'
				I seeCurrentUrlIs '/dashboard'
				I see 'Welcome back', '.notice'		
		

Автодополнение

Умная работа с локаторами


					$I->click('Login');
					$I->click('#loginForm input[type=submit]');
					$I->click('./*[@id='loginForm']/input[@type='submit']');
					$I->click(['name' => 'submit']);
			
		

PageObjects

			$I->click(LoginPage::$submitButton);			
			LoginPage::of($I)			
			  ->login('[email protected]','mysecurepassword');
		

StepObjects

				$I = new AcceptanceTester\UserSteps($scenario);
				$I->logIn('myemail', 'mysecurepassword');
				$I->see('Welcome back', '.notice');
			

Единое API

Selenium WebDriver

Расширяем возможности

				function clickGreenButton() {
				  $this->webDriver->findElement(
            WebDriverBy::cssSelector('#green button')
          )->click();;
        }
        // в тесте:
        $I->clickGreenButton();
			

Environments

Приемочные тесты

✓ Функциональные тесты

Юнит тесты

Простой тест

					$I = new FunctionalTester($scenario);
					$I->amOnPage('/login');
					$I->fillField('email','[email protected]');
					$I->fillField('password','mysecurepassword');
					$I->click('#loginForm input[type=submit]');
					$I->seeCurrentUrlIs('/dashboard');
					$I->see('Welcome back','.notice');			
					$I->seeInSession('user_name','me');
		

Фреймворки

Веб сервисы

				$I = new ApiTester($scenario);
				$I->wantTo('get pending articles via REST API');
				$I->amHttpAuthenticated('service_user','123456');
				$I->sendGET('articles', ['type' => 'pending']);
				$I->seeResponseCodeIs(200);
				$I->seeResponseIsJson();
				$I->seeResponseContains('article: { title: "Article 1"}');
			

Приемочные тесты

Функциональные тесты

✓ Юнит тесты

Юнит тесты

Юнит тест

				function testSavingUser() {
				    $user = new User();
				    $user->setName('Miles');
				    $user->save();
				    $this->assertEquals('Miles', $user->getFullName());
				    $this->tester->seeInDatabase('users',['name' => 'Miles']);
				}			
			

Codeception\AspectMock

				
				$this->assertEquals('users', User::tableName());
				test::double('User', ['tableName' => 'fake_users']);
				$this->assertEquals('fake_users', User::tableName());
			
github.com/Codeception/AspectMock

Specify + Verify

        	$this->specify("returns full name", function() {
                $this->user->firstName = 'Michael';
                $this->user->lastName = 'Bodnarchuk';
                verify($this->user->getFullName())
            	      ->equals('Michael Bodnarchuk');
        	});
			
github.com/Codeception/Specify + github.com/Codeception/Verify

Общие возможности

Code Coverage

Отладочная информация

Документация

Codeception 2.0

Принципы

Нововведения

Паралельный запуск тестов

Паралельный запуск тестов

Codeception это...

Спасибо за внимание

  1. Михаил Боднарчук, автор
  2. Мой скайп: davert.ua
  3. Cайт проекта: codeception.com
  4. И его twitter: @codeception
  5. © <?= date('Y') ?>