Testable Code ... In Joomla!?

Post on 12-Nov-2014

1618 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Writing testable code is also writing better code. Here's how to do it in the context of Joomla CMS

Transcript

TESTABLE CODE ..... IN JOOMLA!?Old School Development Regenerated, or, Doin’ it like a Time Lord

Friday, March 15, 13

Who Is This?Arlen Walker - (Paladin)

@arlenWeb Developer, PKWARE, Inc.

Friday, March 15, 13

CURMUDGEON

Friday, March 15, 13

ANNOYANCE

Friday, March 15, 13

TROUBLEMAKER

Friday, March 15, 13

ARROGANT

Friday, March 15, 13

WASTE EVACUATION CHUTE

Friday, March 15, 13

TEST NAZI

Friday, March 15, 13

That’s Who, But Why?

Friday, March 15, 13

That’s Who, But Why?

40 years development experience

Friday, March 15, 13

That’s Who, But Why?

40 years development experience

15 years on the web

Friday, March 15, 13

That’s Who, But Why?

40 years development experience

15 years on the web

Wrote plugins when they were called Mambots

Friday, March 15, 13

That’s Who, But Why?

40 years development experience

15 years on the web

Wrote plugins when they were called Mambots

Joomla Community Magazine Developer’s Workbench

Friday, March 15, 13

What If You Had A Tool...

Friday, March 15, 13

What If You Had A Tool...

... that could look inside your application?

Friday, March 15, 13

What If You Had A Tool...

... that could look inside your application?

... that would help you write better code, faster?

Friday, March 15, 13

What If You Had A Tool...

... that could look inside your application?

... that would help you write better code, faster?

... that encouraged good development practices?

Friday, March 15, 13

What If You Had A Tool...

... that could look inside your application?

... that would help you write better code, faster?

... that encouraged good development practices?

... that conformed to the advice of major productivity gurus like David Allen and Stephen Covey?

Friday, March 15, 13

What If You Had A Tool...

... that could look inside your application?

... that would help you write better code, faster?

... that encouraged good development practices?

... that conformed to the advice of major productivity gurus like David Allen and Stephen Covey?

...that pointed out what you’re doing now breaks what you did last week?

Friday, March 15, 13

Automated Testing

Kent Beck’s work on Smalltalk testing resulted in SUnit

From there, JUnit was born, and the xUnit series of testing frameworks began

Joomla is written in PHP, so it uses ....

Friday, March 15, 13

PHPUnit

Friday, March 15, 13

Tests Before Code

Kent Beck remembered reading about the “tests first” approach in an “ancient” computer programming manual.

This memory began what is known today as Test Driven Development, an agile development practice that uses tests to define the code that will be written.

Friday, March 15, 13

Write Tests First?Enforces "plan before code"

Focuses the coding on one task at a time

Documents progress

Avoids creating unnecessary code

Ensures resulting code is testable, therefore easily changeable.

Allows immediate refactoring of code, resulting in cleaner, clearer, better code.

Friday, March 15, 13

THE ONE CERTAINTY

Friday, March 15, 13

YOUR CODE WILL CHANGE!

Friday, March 15, 13

Testable Code is Easy to Change

Small Units

Focused on Single Idea

Loosely Coupled

Clean and Clear

Small Units

Focused on a Single Idea

Loosely Coupled

Clean and Clear

Testable CodeModifiable Code

Friday, March 15, 13

DON'T JUST TAKE MY WORD FOR IT

Friday, March 15, 13

David Allen

Before you begin, answer one question:

“What does ‘done’ look like?”

Friday, March 15, 13

Dr. Stephen Covey

Habit 2

Begin With The End In Mind

Friday, March 15, 13

SO WHAT WOULD TESTABLE CODE THAT WORKS IN JOOMLA! LOOK LIKE?

Friday, March 15, 13

mod_random_image — BeforeRequires presence of Joomla code

Depends on specific classes

Must execute code outside of unit to evaluate unit’s performance

Harder to debug issues

Violates "Tell, Don't Ask"

Friday, March 15, 13

Tell, Don't Ask

Procedural code asks for information, makes a decision, and then acts

Object-Oriented code tells an object to act, and the object decides what it can/should do

Friday, March 15, 13

mod_random_image — After

Much simpler code

Easier to understand

All logic now inside object

Simply creates unit and output

No real debugging necessary

Friday, March 15, 13

Helper

Static functionsThis means we can’t replace them

for testing purposesHard-coded to use Joomla

functionsRequires execution of external

codeViolates “Metz Prohibition”

Friday, March 15, 13

“Never Mention a Class Name Within Another Class”

From Sandi Metz

As with all rules of software development, it’s not inviolable.

The specific class is less important than its members

Liskov Substitution Principle

Reduces dependencies on outside code, makes doubling for testing simple.

Friday, March 15, 13

HelperNo static method callsA completely different cms object

can be inserted for testing purposes.Can be tested in isolation from all

Joomla code.No violations of the Metz

Prohibition

Friday, March 15, 13

Test Doubles

Special-purpose objects

Replace parts of a larger system

Receive messages from the code being tested

Report on their interactions with the code being tested

Supply test data

Friday, March 15, 13

PHUnit Test Doubles$this->mock_glue = $this->getMock('JoomlaGlue', array('getBaseUrl', 'strpos', 'getTranslatedText', 'getLayoutPath', 'sendHTML'));

$this->mock_glue->expects($this->once())->method('getBaseURL')->will($this->returnValue('http://www.testingsite.com'));

Checks to be sure getBaseURL() gets called only once, and returns a specific value.

$this->mock_glue->expects($this->exactly(2))->method('strpos')->will($this->returnValue($this->folder));

Checks to be sure strpos() gets called twice and each time returns a specific value.

Friday, March 15, 13

What if it’s not a Module?

Plugins can be set up very similarly to Modules

An idea for Components is to use the Decorator pattern to wrap your class around the Joomla class.

Friday, March 15, 13

Decorator Pattern

Brings in the wrapped object in its constructor

Passes all calls it doesn’t handle itself on to the decorated class

"Prefer composition over inheritance"

Friday, March 15, 13

Decorator

Include all decorated methods as pass-thru’s

... or use the “__call” magic method to pass method calls

public function __construct($client)

{ $this->decorated = $client; }

... overridden and / or new methods here ...

// route all other method calls directly to the decorated object public function __call($method, $args) { // you could also add method_exists check here return call_user_func_array(array($this->decorated, $method), $args); }

Friday, March 15, 13

BUT I DO FRONT-END WORK!I don’t have any way to test, right?

Friday, March 15, 13

Yes, you can!

Template overrides can be tested like modules or plugins -- wrap them with an object that provides links to the information they need, replace them with test data for testing.

But PHPUnit can’t test javascript, can it?

Friday, March 15, 13

Javascript

Selenium2 (WebDriver) works with PHPUnit, but:

Direct UI testing is Fragile

Direct UI testing doesn’t isolate the UI unit being tested

Direct UI testing takes longer than unit testing should take

Friday, March 15, 13

Jasmine

Uses a traditional behavior-focused english-like syntax:

describe - to set the description for a block of tests

it - to describe the specific test

expect - to match the actual output with the expected.

Jasmine-jQuery provides test fixtures and jQuery matchers

https://github.com/velesin/jasmine-jquery

Friday, March 15, 13

A Block of Related Tests

describe( “Description of Test Block”, function () {

...test code goes here...

});

Friday, March 15, 13

Test Setup And Teardown

beforeEach( function () {

.....set up for test to begin.....

});

afterEach( function () {

.....teardown from testing.....

});

Friday, March 15, 13

Fixtures

Added by jasmine-jQuery

Allows you to create a special set of markup to test against.

setFixtures('<div class="event"><a class="showme" style="display:none;">Show</a><a class="hideme" style="display:none;">Hide</a><div class="description">Description</div></div>');

Friday, March 15, 13

Test

it( “What is test about”, function () {

.....actual test happens here.....

});

Friday, March 15, 13

Match Results

expect(actualValue)[.not].toBe(otherValue);

other matchers include toEqual(y), toMatch(regex), toBe[Un]Defined(), toBeNull(), toBeTruthy(), toBeFalsy(), toContain(x), toBeLessThan(x), toBeGreaterThan(y)

jasmine-jQuery adds even more matchers

Friday, March 15, 13

Jasmine Example

Friday, March 15, 13

Originally$('#webinar-click1').click(function() {

$('#webinar-desc1').show('fast', function() {

$('#webinar-click1').fadeOut('fast', function() {

$('#webinar-click-hide1').fadeIn('fast', function() {

});

});

});

});

$('#webinar-click-hide1').click(function() {

$('#webinar-click-hide1').fadeOut('fast', function() {

$('#webinar-desc1').hide('fast', function() {

$('#webinar-click1').fadeIn('fast', function() {

});

});

});

});

Friday, March 15, 13

Testsdescribe("Expanding Descriptions", function () {! beforeEach(function () {! ! setFixtures('<div class="event"><a class="showme" style="display:none;">' +! ! ! 'Show</a><a class="hideme" style="display:none;">Hide</a>' +! ! ! '<div class="description">Description</div></div>');! });! afterEach(function () {! });! it("should not have visible showme button", function () {! ! expect($(".event .showme").first().css("display")).toBe("none");! });! it("should not have visible hideme button", function () {! ! expect($(".event .showme").first().css("display")).toBe("none");! });! it("should display the description", function () {! ! expect($(".event .description").first().css("display")).not.toBe("none");! });});

Friday, March 15, 13

Initializationdescribe("Initializing The Boxes", function () {! beforeEach(function () {! ! setFixtures('<div class="event"><a class="showme" style="display:none;">' +! ! ! 'Show</a><a class="hideme" style="display:none;">Hide</a>' +! ! ! '<div class="description">Description</div></div>');! ! setExpandingBoxes();! });! it("should now have a visible showme button", function () {! ! expect($(".event .showme").first().css("display")).not.toBe("none");! });! it("should not have a visible hideme button", function () {! ! expect($(".event .hideme").first().css("display")).toBe("none");! });! it("should not display the description", function () {! ! expect($(".event .description").first().css("display")).toBe("none");! });});

Friday, March 15, 13

CreditsJasmine

http://pivotal.github.com/jasmine/https://github.com/jcarver989/phantom-jasminehttps://github.com/velesin/jasmine-jqueryhttp://www.theodicius.net/archives/2012/09/25/what-i-did-to-the-jasmine-phantom/

Testable Moduleshttp://magazine.joomla.org/issues/issue-aug-2012/item/822-Towards-A-More-Testable-Module

S.O.L.I.D.http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod

PHPUnithttps://github.com/sebastianbergmann?tab=repositories

Metz Prohibitionhttp://rubyrogues.com/087-rr-book-clubpractical-object-oriented-design-in-ruby-with-sandi-metz/

Tell, Don’t Askhttp://www.ccs.neu.edu/research/demeter/related-work/pragmatic-programmer/jan_03_enbug.pdf

Friday, March 15, 13

Arlen Walker

@arlen on Twitter

Paladin on Github

http://speakerrate.com/talks/20671-testable-code-in-joomla

Friday, March 15, 13

top related