Top Banner
Writing Testable Code (for Magento 1 and 2) Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp
104

Writing Testable Code (for Magento 1 and 2)

Jan 08, 2017

Download

Software

vinaikopp
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Writing Testable Code (for Magento 1 and 2)

Writing Testable Code(for Magento 1 and 2)

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 2: Writing Testable Code (for Magento 1 and 2)

Assumptions

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 3: Writing Testable Code (for Magento 1 and 2)

You know basic PHPUnit.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 4: Writing Testable Code (for Magento 1 and 2)

You want→ Confidence in deploys

→ Experience joy when writing tests→ Have fun doing code maintaince

→ Get more $$$ from testing

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 5: Writing Testable Code (for Magento 1 and 2)

In short, you want→ Testable code

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 6: Writing Testable Code (for Magento 1 and 2)

When is code "testable"?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 7: Writing Testable Code (for Magento 1 and 2)

When testingis simple & easy.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 8: Writing Testable Code (for Magento 1 and 2)

What makes atest simple?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 9: Writing Testable Code (for Magento 1 and 2)

It is simple to write.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 10: Writing Testable Code (for Magento 1 and 2)

It is easy to read.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 11: Writing Testable Code (for Magento 1 and 2)

What does"easy to read"

mean?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 12: Writing Testable Code (for Magento 1 and 2)

It's intent is clear.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 13: Writing Testable Code (for Magento 1 and 2)

The test is short.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 14: Writing Testable Code (for Magento 1 and 2)

Good names.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 15: Writing Testable Code (for Magento 1 and 2)

It only doesone thing.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 16: Writing Testable Code (for Magento 1 and 2)

Clean Codeis for

Production Code & Test Code

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 17: Writing Testable Code (for Magento 1 and 2)

What does"simple to write"

mean?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 18: Writing Testable Code (for Magento 1 and 2)

Test codedepends on

production code

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 19: Writing Testable Code (for Magento 1 and 2)

It are properties of the

production codethat make testing

easy or hard.Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 20: Writing Testable Code (for Magento 1 and 2)

"It's no big thing,but you make big things

out of little things sometimes."~~ Robert Duvall

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 21: Writing Testable Code (for Magento 1 and 2)

What does easy to test code look like?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 22: Writing Testable Code (for Magento 1 and 2)

A bad case of legacy:Event Observer(for Magento 1)

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 23: Writing Testable Code (for Magento 1 and 2)

<?php

use Varien_Event_Observer as Event;

class Netzarbeiter_CustomerActivation_Model_Observer{ // Check if the customer has been activated, if not, throw login error public function customerLogin(Event $event) {...}

// Flag new accounts as such public function customerSaveBefore(Event $event) {...}

// Send out emails public function customerSaveAfter(Event $event) {...}

// Abort registration during checkout if default activation status is false public function salesConvertQuoteAddressToOrder(Event $event) {...}

// Add customer activation option to the mass action block public function adminhtmlBlockHtmlBefore(Event $event) {...}

// Add the customer_activated attribute to the customer grid collection public function eavCollectionAbstractLoadBefore(Event $event) {...}

// Add customer_activated column to CSV and XML exports public function coreBlockAbstractPrepareLayoutAfter(Event $event) {...}

// Remove the customer id from the customer/session, in effect causing a logout public function actionPostdispatchCustomerAccountResetPasswordPost(Event $event) {...}}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 24: Writing Testable Code (for Magento 1 and 2)

Are we going to write Unit Tests?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 25: Writing Testable Code (for Magento 1 and 2)

For > 500 lines of legacy?

Hell NO!Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 26: Writing Testable Code (for Magento 1 and 2)

What would make it simpler to test?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 27: Writing Testable Code (for Magento 1 and 2)

If the class where

smallerit would be simpler to test.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 28: Writing Testable Code (for Magento 1 and 2)

First attempt:Splitting the class based on

purpose.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 29: Writing Testable Code (for Magento 1 and 2)

What does theclass do?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 30: Writing Testable Code (for Magento 1 and 2)

1. Prevents inactive customer logins.2. Sends notification emails.

3. Adds a column to the customer grid.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 31: Writing Testable Code (for Magento 1 and 2)

Lets split it intoNetzarbeiter_CustomerActivation_Model......_Observer_ProhibitInactiveLogins..._Observer_EmailNotifications..._Observer_AdminhtmlCustomerGrid

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 32: Writing Testable Code (for Magento 1 and 2)

<?php

use Varien_Event_Observer as Event;

class Netzarbeiter_CustomerActivation_Model_Observer_ProhibitInactiveLogin{ // Check if the customer has been activated, if not, throw login error public function customerLogin(Event $event) {...}

// Abort registration during checkout if default activation status is false public function salesConvertQuoteAddressToOrder(Event $event) {...}

// Remove the customer ID from the customer/session causing a logout public function actionPostdispatchCustomerAccountResetPasswordPost(Event $event) {...}}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 33: Writing Testable Code (for Magento 1 and 2)

<?php

use Varien_Event_Observer as Event;

class Netzarbeiter_CustomerActivation_Model_Observer_EmailNotifications{ // Flag new accounts as such public function customerSaveBefore(Event $event) {...}

// Send out emails public function customerSaveAfter(Event $event) {...}}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 34: Writing Testable Code (for Magento 1 and 2)

<?php

use Varien_Event_Observer as Event;

class Netzarbeiter_CustomerActivation_Model_Observer_AdminhtmlCustomerGrid{ // Add customer activation option to the mass action block public function adminhtmlBlockHtmlBefore(Event $event) {...}

// Add the customer_activated attribute to the customer grid collection public function eavCollectionAbstractLoadBefore(Event $event) {...}

// Add customer_activated column to CSV and XML exports public function coreBlockAbstractPrepareLayoutAfter(Event $event) {...}}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 35: Writing Testable Code (for Magento 1 and 2)

Is this simplerto test?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 36: Writing Testable Code (for Magento 1 and 2)

Only minor difference in

testing effort.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 37: Writing Testable Code (for Magento 1 and 2)

Why?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 38: Writing Testable Code (for Magento 1 and 2)

The same tests as before.Only split into three classes.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 39: Writing Testable Code (for Magento 1 and 2)

Second attempt:Lets go beyond

superficial changes.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 40: Writing Testable Code (for Magento 1 and 2)

Lets look at the design.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 41: Writing Testable Code (for Magento 1 and 2)

What collaborators are used?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 42: Writing Testable Code (for Magento 1 and 2)

Collaborators:Netzarbeiter_CustomerActivation_Helper_DataMage_Customer_Model_CustomerMage_Customer_Model_SessionMage_Customer_Model_GroupMage_Customer_Helper_AddressMage_Customer_Model_Resource_Customer_CollectionMage_Core_Controller_Request_HttpMage_Core_Controller_Response_HttpMage_Core_ExceptionMage_Core_Model_SessionMage_Core_Model_StoreMage_Sales_Model_Quote_AddressMage_Sales_Model_QuoteMage_Eav_Model_ConfigMage_Eav_Model_Entity_TypeMage_Adminhtml_Block_Widget_Grid_MassactionMage_Adminhtml_Block_Widget_Grid

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 43: Writing Testable Code (for Magento 1 and 2)

Almost all of them are core classes.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 44: Writing Testable Code (for Magento 1 and 2)

Only two classes are part of the module:Netzarbeiter_CustomerActivation_Model_ObserverNetzarbeiter_CustomerActivation_Helper_Data

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 45: Writing Testable Code (for Magento 1 and 2)

Based on the names, why do they exist?

Netzarbeiter_CustomerActivation_Model_ObserverNetzarbeiter_CustomerActivation_Helper_Data

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 46: Writing Testable Code (for Magento 1 and 2)

The names don't tell us anything.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 47: Writing Testable Code (for Magento 1 and 2)

Extract parts by giving them

meaningful names

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 48: Writing Testable Code (for Magento 1 and 2)

But where to start?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 49: Writing Testable Code (for Magento 1 and 2)

Separate business logicfrom the entry points.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 50: Writing Testable Code (for Magento 1 and 2)

Entry points are the places Magento provides us to put our custom code.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 51: Writing Testable Code (for Magento 1 and 2)

Entry points:→ Observers→ Plugins

→ Controllers→ Cron Jobs→ Preferences

→ Console Commands

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 52: Writing Testable Code (for Magento 1 and 2)

Entry points linkBusiness logic

!Magento

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 53: Writing Testable Code (for Magento 1 and 2)

Remove allBusiness Logic

fromEntry Points.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 54: Writing Testable Code (for Magento 1 and 2)

What are the benefits?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 55: Writing Testable Code (for Magento 1 and 2)

For testing:

The custom code can be triggered independently of the entry point.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 56: Writing Testable Code (for Magento 1 and 2)

In or example,what is the

entry point?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 57: Writing Testable Code (for Magento 1 and 2)

Observer

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 58: Writing Testable Code (for Magento 1 and 2)

Old Observer Code:

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 59: Writing Testable Code (for Magento 1 and 2)

public function customerLogin($observer){ $helper = Mage::helper('customeractivation'); if (!$helper->isModuleActive()) { return; }

if ($this->_isApiRequest()) { return; }

$customer = $observer->getEvent()->getCustomer(); $session = Mage::getSingleton('customer/session');

if (!$customer->getCustomerActivated()) { $session->setCustomer(Mage::getModel('customer/customer')) ->setId(null) ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);

if ($this->_checkRequestRoute('customer', 'account', 'createpost')) { $message = $helper->__('Please wait for your account to be activated');

$session->addSuccess($message); } else { Mage::throwException($helper->__('This account is not activated.')); } }}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 60: Writing Testable Code (for Magento 1 and 2)

New Code, without business logic:

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 61: Writing Testable Code (for Magento 1 and 2)

public function customerLogin(Event $event){ if (! $this->isModuleActive()) { return; }

$this->getCustomerLoginSentry()->abortLoginIfNotActive( $event->getData('customer') );}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 62: Writing Testable Code (for Magento 1 and 2)

And this class issimpler to test?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 63: Writing Testable Code (for Magento 1 and 2)

Yes, as there ismuch less logic.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 64: Writing Testable Code (for Magento 1 and 2)

Most of the logic is delegated to collaborators.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 65: Writing Testable Code (for Magento 1 and 2)

$this->getCustomerLoginSentry()->abortLoginIfNotActive( $event->getData('customer'));

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 66: Writing Testable Code (for Magento 1 and 2)

How does the delegation look in

detail?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 67: Writing Testable Code (for Magento 1 and 2)

private static $sentryClass = 'customeractivation/customerLoginSentry';

/** * @return Netzarbeiter_CustomerActivation_Model_CustomerLoginSentry */private function getCustomerLoginSentry(){ return $this->loginSentry ?? Mage::getModel(self::$sentryClass);}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 68: Writing Testable Code (for Magento 1 and 2)

The login sentry can be injected.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 69: Writing Testable Code (for Magento 1 and 2)

That means,it can be replaced by a test double.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 70: Writing Testable Code (for Magento 1 and 2)

Dependency Injection

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 71: Writing Testable Code (for Magento 1 and 2)

DI is a Magento 2 thing, right?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 72: Writing Testable Code (for Magento 1 and 2)

DI can be everywhere!

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 73: Writing Testable Code (for Magento 1 and 2)

Injecting Test Doublesin Magento 1

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 74: Writing Testable Code (for Magento 1 and 2)

Setter Injection

public function testDelegatesToLoginSentry(){ $mockLoginSentry = $this->createMock(LoginSentry::class); $mockLoginSentry->expects($this->once()) ->method('abortLoginIfNotActive');

$observer = new Netzarbeiter_CustomerActivation_Model_Observer();

$observer->loginSentry = $mockLoginSentry;

// ...}

Problematic because it makes the class interface less clean.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 75: Writing Testable Code (for Magento 1 and 2)

Constructor Injection

public function testDelegatesToLoginSentry(){ $mockLoginSentry = $this->createMock(LoginSentry::class); $mockLoginSentry->expects($this->once()) ->method('abortLoginIfNotActive');

$observer = new Netzarbeiter_CustomerActivation_Model_Observer( $mockLoginSentry );

// ...}

Problematic because standard Magento 1 instantiation.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 76: Writing Testable Code (for Magento 1 and 2)

Ugly but works fine.

/** * @param LoginSentry $loginSentry */public function __construct($loginSentry = null){ $this->loginSentry = $loginSentry;}

// ...

private function getCustomerLoginSentry(){ return isset($this->loginSentry) ?? Mage::getModel(self::$sentry);}

Optional Dependencies?! (WTF LOL)Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 77: Writing Testable Code (for Magento 1 and 2)

Injected collaboratorsmake for simple tests!

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 78: Writing Testable Code (for Magento 1 and 2)

Delegation allow us to createclasses with a specific purpose.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 79: Writing Testable Code (for Magento 1 and 2)

We can give descriptive names.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 80: Writing Testable Code (for Magento 1 and 2)

Model with specific responsibilityclass Netzarbeiter_CustomerActivation_Model_CustomerLoginSentry

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 81: Writing Testable Code (for Magento 1 and 2)

public function abortLoginIfNotActive( Mage_Customer_Model_Customer $customer) { if (! $customer->getData('customer_activated') { $this->getSession()->logout(); $this->getDisplay()->showLoginAbortedMessage(); }}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 82: Writing Testable Code (for Magento 1 and 2)

This business logic is now independent of the entry point

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 83: Writing Testable Code (for Magento 1 and 2)

It can be called from anywhere

→ Observer→ Controller

→ Model Rewrite→ Test

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 84: Writing Testable Code (for Magento 1 and 2)

Back to the example code...

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 85: Writing Testable Code (for Magento 1 and 2)

There is one other thing here that makes testing easier:

public function customerLogin(Event $event){ if (! $this->isModuleActive()) { return; }

$this->getCustomerLoginSentry()->abortLoginIfNotActive( $event->getData('customer') );}

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 86: Writing Testable Code (for Magento 1 and 2)

No magic method call.// Old code:$event->getCustomer();

// New code:$event->getData('customer')

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 87: Writing Testable Code (for Magento 1 and 2)

Why does thatimprove testability?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 88: Writing Testable Code (for Magento 1 and 2)

Creating a mock withmagic methods is ugly!

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 89: Writing Testable Code (for Magento 1 and 2)

Noisy code in test is distracting.$methods = array_merge( get_class_methods(Event::class), ['getCustomer']);$mockEvent = $this->getMockBuilder(Event::class) ->setMethods($methods) ->getMock();

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 90: Writing Testable Code (for Magento 1 and 2)

Much simpler: $mockEvent = $this->createMock(Event::class);

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 91: Writing Testable Code (for Magento 1 and 2)

SummaryWriting Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 92: Writing Testable Code (for Magento 1 and 2)

What makes code simple to test?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 93: Writing Testable Code (for Magento 1 and 2)

→ Separation ofBusiness Logic

andEntry Points

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 94: Writing Testable Code (for Magento 1 and 2)

→ Small classes

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 95: Writing Testable Code (for Magento 1 and 2)

→ Encapsulation of Business Logic inspecific classes

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 96: Writing Testable Code (for Magento 1 and 2)

→ Delegation to injectable dependencies

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 97: Writing Testable Code (for Magento 1 and 2)

→ Real methodsover

magic methods

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 98: Writing Testable Code (for Magento 1 and 2)

Is there more?

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 99: Writing Testable Code (for Magento 1 and 2)

→ Law of Demeter.→ Separation of code that causes side

effects from code that return a value.→ No method call chaining.

→ Single level of detail within methods.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 100: Writing Testable Code (for Magento 1 and 2)

Lets keep these for another time.

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 101: Writing Testable Code (for Magento 1 and 2)

But most importantly...

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 102: Writing Testable Code (for Magento 1 and 2)

...have fun writing tests!

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 103: Writing Testable Code (for Magento 1 and 2)

(tell you me comment)(ask? you me question)

(thank you)

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp

Page 104: Writing Testable Code (for Magento 1 and 2)

http://mage2katas.com/

Writing Testable Code in Magento 1 and 2 - #MM16PL 2016-09-19 - twitter://@VinaiKopp