• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Nashville Symfony Functional Testing
 

Nashville Symfony Functional Testing

on

  • 4,348 views

Symfony functional testing is vital to your project's success. Learn how to easily extend the framework to fit your application's custom needs.

Symfony functional testing is vital to your project's success. Learn how to easily extend the framework to fit your application's custom needs.

Statistics

Views

Total Views
4,348
Views on SlideShare
4,312
Embed Views
36

Actions

Likes
2
Downloads
47
Comments
0

2 Embeds 36

http://www.slideshare.net 35
http://www.sfexception.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Nashville Symfony Functional Testing Nashville Symfony Functional Testing Presentation Transcript

    • FUNCTIONAL TESTING (overview) Functional tests validate parts of your applications. Functional tests simulate a browsing session to assert desired user outcomes. They automate requests and check elements in the response. It is advantageous to write your functional tests to correspond to individual user stories. User Story: As an Administrator I want to create a company so I can manage companies Wednesday, January 6, 2010
    • WHY WRITE THEM? - BETTER TEST COVERAGE!! - Cover areas unit tests can’t reach - Unit Tests: Model Layer - Functional Tests: View and Control Layers - Mimic Functional QA - Write tests according to client-approved user stories. Wednesday, January 6, 2010
    • TOOLS FOR FUNCTIONAL TESTING Cucumber “Cucumber is designed to allow you to execute feature documentation written in plain text (often known as ‘stories’).” •We will discuss this later Selenium “Selenium is written in JavaScript; it's designed to run in a real browser to test compatibility with a real browser” •Uses a real browser •Writes test in JavaScript, can play back through any browser Wednesday, January 6, 2010
    • FUNCTIONAL TESTING IN SYMFONY - Bootstrap Symfony Core - sfBrowser - Symfony class simulating a true browser - Testing Blocks - sfTestFunctional split into multiple classes - sfTesterResponse, sfTesterRequest, sfTesterDoctrine, sfTesterUser, sfTesterForm - Extend the functional test framework for custom functionality Wednesday, January 6, 2010
    • EXTEND THE TEST FRAMEWORK Subclass sfTestFunctional class csTestFunctional extends sfTestFunctional { public function clickAndCheck($link, $module, $action, $statusCode = 200) { return $this->click($link)->isModuleAction($module, $action, $statusCode); } public function isModuleAction($module, $action, $statusCode = 200) { $this->with('request')->begin()-> isParameter('module', $module)-> isParameter('action', $action)-> end()-> with('response')->begin()-> isStatusCode($statusCode)-> end(); return $this; } } Wednesday, January 6, 2010
    • USE FIXTURES // test/data/urls.yml - url: /blog Create a YAML file to hold module: blog action: index statusCode: 200 data - url: /blog/new module: blog action: new AND... statusCode: 200 - url: /blog/edit module: blog action: edit Simplify Repetitive Tests! statusCode: 401 // test/functional/frontend/routeTest.php foreach(sfYaml::load(sfConfig::get('sf_test_dir').'/data/forms.yml') as $route) { $browser ->get($route['url']) ->isModuleAction($route['module'], $route['action'], $route['statusCode']) ; } Wednesday, January 6, 2010
    • CREATE YOUR OWN TESTER Extend sfTesterForm class csTesterForm extends sfTesterForm { // Called at every occurence of $browser->with('form') public function initialize() { // Load form into local variable parent::initialize(); } // Called when a page is requested // (at every occurence of $browser->call()) public function prepare() { } public function fill($name, $values = array()) { $formValues = Doctrine_Lib::arrayDeepMerge($this->getFormValues($name), $values); foreach ($formValues as $key => $value) { $this->setDefaultField($key, $value); } return $this->getObjectToReturn(); } } Wednesday, January 6, 2010
    • Extend sfTesterForm (continued) // test/data/forms.yml login_bad: signin: username: admin password: wrongpassword login: signin: Create Form Fixtures username: admin password: rightpassword login2: signin[username]: admin signin[password]: rightpassword Load them into your Tester! // lib/test/csTesterForm.class.php public function __construct(sfTestFunctionalBase $browser, $tester) { parent::__construct($browser, $tester); if (file_exists(sfConfig::get('sf_test_dir').'/data/forms.yml')) { $this->setFormData(sfYaml::load(sfConfig::get('sf_test_dir').'/data/forms.yml')); } } // test/functional/backend/loginTest.php $browser = new csTestFunctional(new sfBrowser(), null, array('form' => 'csTesterForm')); Instantiate Your Classes Wednesday, January 6, 2010
    • USE FACTORIES Helpful classes to generate objects and data class sfFactory { protected static $lastRandom = null; public static function generate($prefix = '') { self::$lastRandom = $prefix.rand(); return self::$lastRandom; } public static function last() { if (!self::$lastRandom) { throw new sfException("No previously generated random available"); } return self::$lastRandom; } } Wednesday, January 6, 2010
    • PUTTING IT ALL TOGETHER $browser = new csTestFunctional(new sfBrowser(), null, array('form' => 'csTesterForm', 'doctrine' => 'sfTesterDoctrine')); $browser->info('Create a new Company'); Initialize your testers $browser ->login() ->get('/company/new') ->with('form')->begin() ->fill('company', array('company[name]' => sfFactory::generate('Company'))) ->end() Fill the form with a ->info('Create Company "'.sfFactory::last().'"') unique value ->click('Save and add') ->with('form')->begin() ->hasErrors(false) ->end() ->followRedirect() Verify record exists ->with('doctrine')->begin() ->check('Company', array('name' => sfFactory::last())) ->end() ; Wednesday, January 6, 2010
    • Success! Wednesday, January 6, 2010
    • CAN YOU THINK OF OTHER USEFUL TESTERS? Wednesday, January 6, 2010
    • USE PLUGINS swFunctionalTestGenerationPlugin Add to your dev toolbar Quickly stub symfony functional tests while clicking through the browser Wednesday, January 6, 2010
    • SO YOU WANNA TEST YOUR PLUGINS? sfTaskExtraPlugin $ ./symfony generate:plugin sfScraperPlugin --module=sfScraper --test-application=frontend Plugin Skeleton Test Fixtures Wednesday, January 6, 2010
    • sfTaskExtraPlugin (continued) Run all plugin tests $ ./symfony test:plugin sfScraperPlugin Connect plugin tests in ProjectConfiguration and.... // config/ProjectConfiguration.class.php public function setupPlugins() { $this->pluginConfigurations['sfScraperPlugin']->connectTests(); } Run plugin tests alongside project tests $ ./symfony test:all Run tests individually $ ./symfony test:unit sfScraper $ ./symfony test:functional frontend sfScraperActions Wednesday, January 6, 2010
    • A LITTLE TASTE OF CUCUMBER Scenario: See all vendors Uses “Scenarios” Given I am logged in as a user in the administrator role And There are 3 vendors When I go to the manage vendors page Then I should see the first 3 vendor names that are then $this->given("I am logged in as a user in the (.*) role", function($browser, $matches) { $browser->get('/') interpreted using ->with('form')->begin() ->fill('login_'.$matches[1]) ->end() “Steps” ; }); ->click('Sign in') Wednesday, January 6, 2010
    • CHECK OUT MORE Selenium plugin to integrate with Symfony - http://github.com/jatimo/cesTestSelenium • Cucumber - http://wiki.github.com/aslakhellesoy/cucumber • Poocumber! - http://github.com/bshaffer/Symfony-Snippets/tree/master/Poocumber/ • Presentation Notes - http://github.com/bshaffer/Symfony-Snippets/tree/master/Presentation-Notes/ 2010-02-05-FunctionalTesting Wednesday, January 6, 2010
    • CONTACT Brent Shaffer bshafs@gmail.com http://brentertainment.com http://symplist.net Wednesday, January 6, 2010