unit and functional testing in symfony introduction to...

Post on 18-Oct-2020

35 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Unit and Functional Testing in SymfonyUnit and Functional Testing in Symfony//

Introduction to ReflectionIntroduction to Reflection

Shawn Biddle(shawncplus)PHP Dev, STUDIO, llc

http://www.whoisstudio.com

DO THEM!!1one!

Unit TestsUnit Tests

What Unit Tests Are ForWhat Unit Tests Are For

Revision 1: Author: shawnbfunction hello(){ return 'world';}

Revision 2: Author: jonrfunction hello(WorldStringClass $world){ return $world->name;}

shawnb was smart and wrote a unit test when he created the hello() function.

$test->is(hello(), 'world', 'hello() returns ”world”'); // PASS

jonr commits his change without running the unit test then shawnb updates and runs his test and it fails. Now shawnb can make jonr wear the dunce hat for the day because he broke the function.

$test->is(hello(), 'world', 'hello() returns ”world”'); // FAIL

What Unit Tests Are NOT ForWhat Unit Tests Are NOT For

➔ Unit tests are NOT human QA➔ Unit tests are NOT functional QA➔ Unit tests are NOT a replacement for communication

Unit tests are not an end-all replacement for someone looking over your code. They do not test implementations of objects/functions. They definitely do not remove the need for communication with other developers.

Unit Tests in SymfonyUnit Tests in Symfony

<?php include(dirname(__FILE__).'/../bootstrap/unit.php');require_once(dirname(__FILE__).'/../../lib/strtolower.php'); $t = new lime_test(7, new lime_output_color()); // strtolower()$t->diag('strtolower()');$t->isa_ok(strtolower('Foo'), 'string', 'strtolower() returns a string');$t->is(strtolower('FOO'), 'foo', 'strtolower() transforms the input to lowercase');$t->is(strtolower('foo'), 'foo', 'strtolower() leaves lowercase characters unchanged');$t->is(strtolower('12#?@~'), '12#?@~', 'strtolower() leaves non alphabetical characters unchanged');$t->is(strtolower('FOO BAR'), 'foo bar', 'strtolower() leaves blanks alone');$t->is(strtolower('FoO bAr'), 'foo bar', 'strtolower() deals with mixed case input');$t->is(strtolower(''), 'foo', 'strtolower() transforms empty strings into foo');

Unit Testing FunctionsUnit Testing Functions

Testing With FixturesTesting With Fixtures

<?php include(dirname(__FILE__).'/../bootstrap/unit.php'); require_once($sf_symfony_lib_dir.'/yaml/sfYaml.class.php');

$testCases = sfYaml::load(dirname(__FILE__).'/fixtures.yml'); $t = new lime_test(count($testCases), new lime_output_color());

// isPathAbsolute() $t->diag('isPathAbsolute()'); foreach ($testCases as $case) { $t->is(sfToolkit::isPathAbsolute($case['input']), $case['output'],$case['comment']); }

- input: '/test' output: true comment: isPathAbsolute() returns true if path is absolute- input: 'test' output: false comment: isPathAbsolute() returns false if path is relative

Works the same in Doctrine and Propel(really)

Accessing the DatabaseAccessing the Database

include(dirname(__FILE__).'/../bootstrap/unit.php');new sfDatabaseManager(ProjectConfiguration::getApplicationConfiguration('public', 'home', true));

// Test directory structuretest/ unit/ myFunctionTest.php mySecondFunctionTest.php foo/ barTest.php

> ./symfony test:unit myFunction ## Run myFunctionTest.php> ./symfony test:unit myFunction mySecondFunction ## Run both tests> ./symfony test:unit 'foo/*' ## Run barTest.php> ./symfony test:unit '*' ## Run all tests (recursive)

Putting It TogetherPutting It Together

DO THEM!!1one!

Functional TestsFunctional Tests

What Functional Tests Are ForWhat Functional Tests Are For

Short AnswerFunctional tests validate parts of your applications.

Long AnswerThey simulate a browsing session, make requests, and check elements in the response, just like you would do manually to

validate that an action does what it's supposed to do. In functional tests, you run a scenario corresponding to a use case.

What Functional Tests Are NOT ForWhat Functional Tests Are NOT For

● Functional tests are NOT human QA● Functional tests are NOT functional QA● Functional tests are NOT a replacement for communication

Functional tests are not an end-all replacement for someone looking over your code. They definitely do not remove the need for communication with other developers.

Functional Tests in SymfonyFunctional Tests in Symfony

sfTestBrowser FunctionssfTestBrowser Functions

getAndCheck($module, $action, Retrieves and checks an action $url = null, $code = 200)throwsException($class = null,

$message = null) Tests if an exception is thrown by the latest request

isResponseHeader($key, $value) Tests for a response header.

isStatusCode($statusCode = 200) Tests a status code for the current browser

call($uri, $mothod = "get", Call a request $parameters = array(), $changeStack = true)

isRedirected($boolean = true) Tests if current request has been redirected

...

See http://www.symfony-project.org/api/1_1/sfTestBrowser for the full list.

checkResponseElementcheckResponseElement

The behavior of the checkResponseElement() method depends on the type of the second argument that it receives:

➔ If it is a Boolean, it checks that an element matching the CSS selector exists.➔ If it is an integer, it checks that the CSS selector returns this number of results.➔ If it is a regular expression, it checks that the first element found by the CSS selector matches it.➔ If it is a regular expression preceded by !, it checks that the first element doesn't match the pattern.➔ For other cases, it compares the first element found by the CSS selector with the second argument as a string.

checkResponseElement ($selector, $value = true, $options = array())

checkResponseElement is incredibly powerful and can go much more in depth than this.http://www.symfony-project.org/book/1_1/15-Unit-and-Functional-Testing#Using CSS Selectors

$b = new sfTestBrowser();$b->get('/foobar/1')-> checkResponseElement('form input[type="hidden"][value="1"]', true);

// Test directory structuretest/ functional/ frontend/ myModuleActionsTest.php myScenarioTest.php backend/ myOtherScenarioTest.php

## Run all functional tests for one application, recursively> symfony test-functional frontend

## Run one given functional test> symfony test-functional frontend myScenario

## Run several tests based on a pattern> symfony test-functional frontend my*

Putting It TogetherPutting It Together

Using Lime Outside of SymfonyUsing Lime Outside of Symfony

Download/Checkout the Lime framework from: http://svn.symfony-project.com/tools/lime/trunk/lib/lime.php

require_once('/path/to/lime/lime.php');

Symfony Lime Documentation(and Cheatsheet):http://trac.symfony-project.org/wiki/LimeTestingFramework

PHP Reflection APIPHP Reflection API

Requirements➔PHP Version >= 5➔The niche need to use it

What is it?A collection of classes and one interface to ”reverse-engineer” classes, interfaces, functions and methods.

PHP Reflection APIPHP Reflection API

Classes in the Reflection API➔ReflectionException➔ReflectionFunction➔ReflectionParameter➔ReflectionClass➔ReflectionObject➔ReflectionMethod➔ReflectionProperty➔ReflectionExtension

Interfaces in the Reflection API➔Reflector

php.net/Reflection

PHP Reflection APIPHP Reflection API

class Reflection { }interface Reflector { }class ReflectionException extends Exception { }class ReflectionFunction extends ReflectionFunctionAbstract

implements Reflector { }class ReflectionParameter implements Reflector { }class ReflectionMethod extends ReflectionFunctionAbstract

implements Reflector { }class ReflectionClass implements Reflector { }class ReflectionObject extends ReflectionClass { }class ReflectionProperty implements Reflector { }class ReflectionExtension implements Reflector { }

Heirarchy

PHP Reflection APIPHP Reflection API

Recipe #1Checking for Function Documentation

$instance = new SomeClass();$refclass = new ReflectionClass($instance);$test->diag('Testing layout of '.get_class($instance));

$test->diag('Methods:');

//Check for documentationforeach($refclass->getMethods() as $method) { if($method->getDocComment() == '') { $test->output->red_bar(

sprintf('WARNING: %s does not have documentation',get_class($instance).'::'.$method->getName())

); } $doc_comment = $method->getDocComment(); if(preg_match_all('/(?<todo>TODO:.+)/', $doc_comment, $todos)) { $test->output->info(

sprintf("In method `%s`:", get_class($instance).'::'.$method->getName()));

foreach($todos['todo'] as $todo) { $test->output->info("\t".$todo); } }}

PHP Reflection APIPHP Reflection API

Recipe #2Method Structure Testing

top related