Magento Development Company - Magento Development India, Magento Development Services
Getting your Hands Dirty Testing Magento 2 (at London Meetup)
Transcript of Getting your Hands Dirty Testing Magento 2 (at London Meetup)
GETTING YOUR HANDS DIRTY
TESTING MAGENTO 2
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
ME
Freelance Developer & Trainerhttps://github.com/vinai
https://twitter.com/vinaikopp
Dev since 1998PHP WebDev since PHP3 (1999)
Magento since 2008-01-01Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TESTINGGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
WHO IS DOING IT?
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
WHAT TOOL?
> PHPUnit?> Behat && PHPSpec?
> Selenium?> Codeception?
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
BUZZWORD BINGO
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
BUZZWORD I:
UNIT TESTGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
$ vendor/bin/phpunit -c "dev/tests/unit/phpunit.xml.dist"
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
$ alias unit-test="$(pwd)/vendor/bin/phpunit -c $(pwd)/dev/tests/unit/phpunit.xml.dist"
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
$ unit-test
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
$ unit-test "app/code/My/Module/Test/Unit"
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TRY ITvendor/bin/phpunit \ -c "dev/tests/unit/phpunit.xml.dist" \ vendor/magento/module-catalog/Test/Unit/Block
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
BUZZWORD II:
INTEGRATION TEST
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
WHAT IS THE DIFFERENCE?
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
REAL OBJECTS INTERACT
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
INTEGRATION TESTS NEED THERUNTIME ENVIRONMENT
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
A failing unit test tells me exactly where my code is broken.
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
A failing integration test only tells me that something is broken.
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Separate DBdev/tests/integration/etc/install-config-mysql.php.dist
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
$ vendor/bin/phpunit -c dev/tests/integration/phpunit.xmlCould not read "dev/tests/integration/phpunit.xml".
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
$ cd dev/tests/integration$ ../../../vendor/bin/phpunit
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Every run gets it's ownetc, pub and var dirs
dev/tests/integration/tmp/
sandbox-0-b79c13eb842cf3211459b11c775bfbde/
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
BUZZWORD III:
TDDGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
WHAT IS TDD?Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
THE 3 RULESGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
I. No production code without a failing unit test
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
II. Once there is a failing unit test, stop and make it pass
by writing production code
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
III. Once the test passes, stop writing production code
until you have a failing unit test again
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TDD FOR MAGENTO 2
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
NO DIFFERENCEGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
</TDD>Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
To learn more about TDD,check out the Clean CodersVideos from Robert C. Martin
http://cleancoders.com
(or do a training)
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
INTEGRATION TESTSFOR MAGENTO 2
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
VERY SPECIFICGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
PLATFORM KNOWLEDGE
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Magento 2 Testing Framework
dev/tests/integration/framework
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Test Framework ObjectManagerMagento\TestFramework\ObjectManager::getInstance()
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Dependencies$configReader = $objectManager->create(Reader::class);
$deploymentConfig = $objectManager->create( DeploymentConfig::class, ['reader' => $configReader]);
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
BUZZWORD IV
FIXTURESGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Fix the system into a known statebefore a test is executed.
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Simple PHP Scripts
Relative to dev/tests/integration/testsuite
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
/** * @magentoDataFixture Magento/Sales/_files/order.php * @magentoDataFixture Magento/Customer/_files/customer.php */public function testSomethingWithAnOrderAndACustomer(){ // ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
CONFIG FIXTURES
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Store Scope/** * @magentoConfigFixture current_store catalog/price/scope 1 */public function testDoesSomeoneReadThisHelpMeLetMeOut(){ // ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Global Scope/** * @magentoConfigFixture currency/options/allow USD */public function testHowMashAndPieTastes(){ // ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
BUZZWORD V
TEST ISOLATION
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
FRESH INSTALLFOR EACH TEST RUN
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
dev/tests/integration/phpunit.xml.dist
<phpunit> ... <php> ... <const name="TESTS_CLEANUP" value="enabled"/> ... </php> ...</phpunit>
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TESTS_CLEANUP== disabled
SPEEDS THINGS UP
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TESTS_CLEANUP== disabled
MANUAL CLEANUP REQUIRED
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
integration/tmp/sandbox-*
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
DATABASE ISOLATION
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TRANSACTIONSOR
ROLLBACK SCRIPTS
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TRANSACTIONS/** * @magentoDbIsolation enabled */ public function testWithoutSideEffects { // ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
TRANSACTIONS/** * @magentoDataFixture Magento/Foo/_files/bar.php */ public function testTheFixtureIsAppliedWithinATransaction { // ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
ROLLBACK SCRIPTS/** * @magentoDataFixture Magento/Customer/_files/customer.php * @magentoDbIsolation disabled */public function testTransactionalCode(){ // ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Before Testinclude 'Magento/Customer/_files/customer.php';
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
After Testinclude 'Magento/Customer/_files/customer_rollback.php';
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
APPLICATION ISOLATION
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
REINSTANTIATEALMOST EVERYTHING
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
RESET MAGENTO AFTER TEST/** * @magentoAppIsolation enabled */public function testTestWithSingletons(){
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Controller Tests: Automatic resetclass FooBarIndexActionTest extends \Magento\TestFramework\TestCase\AbstractController{ public function testTheLayoutIsRendered() { $this->dispatch('foo/bar/index');
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
REMEMBERTHIS
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
ISOLATEYOUR TESTS
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
AND ALL WILL BE
GOODGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
[breathing pause]
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
APPLICATION AREA
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
APP AREAS
global
frontend
adminhtml
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
/** * @magentoAppArea frontend */class AddressesTest extends \PHPUnit_Framework_TestCase{
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
MORE AREAS
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
webapi_rest
webapi_soap
cron
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
\Magento\TestFramework\App\State
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
public function testPluginInWebapiRestScope(){ $class = \Magento\TestFramework\App\State::class; $appAreaState = $this->objectManager->get($class);
$appAreaState->setAreaCode('webapi_rest');
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
protected function tearDown(){ // ... $appAreaState->setAreaCode(null); }
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
ACTION[CONTROLLER]
TESTSGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
FRONTEND
\Magento\TestFramework\TestCase\AbstractController
ADMINHTML
\Magento\TestFramework\TestCase\AbstractBackendController
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
EXAMPLE!
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Event Observer for:sales_order_place_after
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
I. TESTING THE CONFIGURATION
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
public function testTheModuleRegistersASalesOrderPlaceAfterObserver(){ $class = \Magento\Framework\Event\Config::class; $eventConfig = ObjectManager::getInstance()->create($class); $observers = $eventConfig->getObservers('sales_order_place_after');
$this->assertArrayHasKey('meetup_observer', $observers);
$expectedClass = \Meetup\Observer\Observer\SalesOrderPlaceAfter::class; $this->assertSame($expectedClass, $observers['meetup_observer']['instance']);
$this->assertFalse($observers['meetup_observer']['shared']);}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
1/2) Get the config in array format$class = \Magento\Framework\Event\Config::class;$eventConfig = ObjectManager::getInstance()->create($class);
$event = 'sales_order_place_after';$observers = $eventConfig->getObservers($event);
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
2/2) Assert config values$this->assertArrayHasKey('meetup_observer', $observers);
$this->assertSame( SalesOrderPlaceAfter::class, $observers['meetup_observer']['instance']);
$this->assertFalse($observers['meetup_observer']['shared']);
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
II. TESTING THE OBSERVER
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
O_0(NOTHING TO TEST)
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
III. INTEGRATION TEST
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
Our observer has no side effects.We have to improvise...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
/** * @magentoDataFixture Magento/Sales/_files/order.php */public function testSalesOrderPlaceAfterObserverIsCalled(){ $this->injectMockObserverWithExpectation();
$order = $this->getOrderFixture();
$this->objectManager ->create(OrderManagementInterface::class) ->place($order);}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
public function injectMockObserverWithExpectation(){ $mockObserver = $this->getMock(SalesOrderPlaceAfter::class); $mockObserver->expects($this->once())->method('execute');
$this->registerObserverTestDouble($mockObserver);}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
private function registerObserverTestDouble($mockObserver){ $class = \Magento\Framework\Event\Config\Data::class; $eventConfigData = $this->objectManager->get($class);
$event = 'sales_order_place_after'; $name = 'meetup_observer';
$eventConfigData->merge( [$event => [$name => ['shared' => true]]] );
// ...}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
private function registerObserverTestDouble($mockObserver){ // ...
$this->objectManager->addSharedInstance( $mockObserver, SalesOrderPlaceAfter::class );}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
/** * @magentoDataFixture Magento/Sales/_files/order.php */public function testSalesOrderPlaceAfterObserverIsCalled(){ // ...
$order = $this->getOrderFixture();
// ...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
private function getOrderFixture(){ $class = OrderRepositoryInterface::class; $orderRepository = $this->objectManager->create($class);
$criteria = $this->objectManager ->create(SearchCriteriaBuilder::class) ->addFilter('increment_id', '100000001') ->create();
$result = $orderRepository->getList($criteria);
return array_values($result->getItems())[0];}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
/** * @magentoDataFixture Magento/Sales/_files/order.php */public function testSalesOrderPlaceAfterObserverIsCalled(){ $this->injectMockObserverWithExpectation();
$order = $this->getOrderFixture();
$this->objectManager ->create(OrderManagementInterface::class) ->place($order);}
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
GO FORTHAND TEST
ALL THINGS!Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
ONE MORE THING...
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
MAGE2KATASGetting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
MAGE2KATAS
> Screencast Series> Examples
> Code Katas
mage2katas.com
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp
THANK YOU <3
Getting your hands dirty Testing Magento 2 - Magento London Meetup, Feb. 2016 - ! - [email protected] - twitter://@VinaiKopp