Appetite comes with testing

Preview:

DESCRIPTION

An overview of the benefits of testing and a secure adventure: Test Driven Development of NmnMultiUserBundle

Citation preview

Change begins with awareness

Appetite comes with testing

“It's a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there's no knowing where you might be swept off to.”

J.R.R. Tolkien, The Lord of the Rings

Change begins with awareness

Defect Cost Increase

Change begins with awareness

Defect Cost Increase

Change begins with awareness

Stress cycle

Change begins with awareness

Testing as...

documentation

Change begins with awareness

Testing as...

instrument forcooperation

Change begins with awareness

Testing as...

instrument foropen source cooperation

Change begins with awareness

Pair programming

Change begins with awareness

All begins with...

...a need

Change begins with awareness

And...

“Supporting multiple user classes is not easy at all. It would make the bundle code far more complex as we would basically need to change all places interacting with the user to be able to handle all user classes. I don't really want to go this way (it will also make it more likely to introduce bugs).”

...a delusion

Change begins with awareness

But...

In Symfony2, all core classes use the service container, so it is easy to extend, configure and use any object

...a hope

Change begins with awareness

Service ContainerDependency Injection Container

use Acme\HelloBundle\Mailer;

$mailer = new Mailer('sendmail');$mailer->send('info@netmeans.net', ... );

Change begins with awareness

Service ContainerDependency Injection Container

class Mailer{ private $mailerType; public function __construct($mailerType) {

$this->mailerType = $mailerType } public function send($to, ...) { ... }}

services: my_mailer: class: Acme\HelloBundle\Mailer arguments: [sendmail]

Change begins with awareness

Service ContainerDependency Injection Container

class HelloController extends Controller{ public function sendEmailAction() { $mailer = $this->get('my_mailer'); $mailer->send('info@netmeans.net', ... ); }}

Change begins with awareness

FOSUserBundle

fos_user: db_driver: orm firewall_name: main user_class: Acme\UserBundle\Entity\User

Change begins with awareness

FOSUserBundle

fos_user: db_driver: orm firewall_name: main user_class: Acme\UserBundle\Entity\User

service: user_manager: custom_user_manager

Change begins with awareness

So ...

...a solution

We have to create our custom UserManager that accepts in the constructor an object that have the responsibility to discriminate user types

Change begins with awareness

First of all: test

We start writing some functional tests to check correct integration of FOSUserBundle

Change begins with awareness

Now we feel good

We can extends FOSUser without pain improving changes step by step

Change begins with awareness

Custom UserManager

Class UserManager extends FOS\UserBundle\Entity\UserManager{

protected $userDiscriminator;

public function __construct(..., UserDiscriminator $userDiscriminator)

public function getClass(){

return $this->userDiscriminator->getClass();}

}

Change begins with awareness

UserDiscriminator

public function getClass(){ return 'Acme/UserBundle/Entity/UserOne';}

Change begins with awareness

From here it's all smooth

With little iterations, we improve UserManager and UserDiscriminator with unit and functional tests, passing from a dirty code to a more elegant one

Change begins with awareness

NmnMultiUserBundle

fos_user: db_driver: orm firewall_name: main user_class: Acme\UserBundle\Entity\User service: user_manager: nmn_user_manager registration: form: handler: nmn_user_registration_form_handler profile: form: handler: nmn_user_profile_form_handler

Change begins with awareness

NmnMultiUserBundle

parameters: nmn_user_discriminator_parameters: classes: user_one: entity: Acme\UserBundle\Entity\UserOne registration: Acme\UserBundle\Form\Type\RegistrationUserOneFormType profile: Acme\UserBundle\Form\Type\ProfileUserOneFormType factory: user_two: entity: Acme\UserBundle\Entity\UserTwo registration: Acme\UserBundle\Form\Type\RegistrationUserTwoFormType profile: Acme\UserBundle\Form\Type\ProfileUserTwoFormType factory:

Change begins with awareness

NmnMultiUserBundle

Ok, it is an hack :)

A lazy way to use for free most of the functionality of FOSUserBundle ...

... but it is ready to be improved by anyone.

Change begins with awareness

NmnMultiUserBundle

github.com/netmeansnet/NmnMultiUserBundle

github.com/netmeansnet/NmnMultiUserBundleSandbox

travis-ci.org/#!/netmeansnet/NmnMultiUserBundle

@leonardo_nmn

@euxpom

Change begins with awareness

Some Books

I know this sounds strident and unilateral, but given the record I don't think the surgeons should have to defend hand-washing, and I don't think programmers should have to defend TDD

The Clean Coder

A code of Conduct for Professional Programmers

Martin, Robert C.

Some Books

In software development, “perfect” is a verb, not an adjective

Extreme Programming Explained

Embrace Change

Beck, Kent

Change begins with awareness

In XP, testing is as important as programming

Change begins with awareness

Some Books

Building testable applications is Hard

The Grumpy Programmer's Guide To BuildingTestable Applications in PHP

Hartjes, Chris

The reason for investing in automated testing is obvious: any bugs you catch before your application makes it into production cost less in terms of resources (money, developer time) to fix than fixing it into production

Recommended