why, what, and how: testing in 2014 · web application » presentation (presentation model, view,...
TRANSCRIPT
![Page 1: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/1.jpg)
Why, What, and How: Testing in 2014Sebastian Bergmann | June 3rd 2014
![Page 2: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/2.jpg)
Sebastian BergmannDriven by his passion to help developers build better software.
![Page 3: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/3.jpg)
sharing experience
![Page 4: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/4.jpg)
Web Application» Presentation
(Presentation Model, View, Template)
» Application Logic(HTTP Abstraction, Routing, Controller)
» Domain Logic
» Persistence
![Page 5: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/5.jpg)
![Page 6: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/6.jpg)
<?phpuseuse Behat\Mink\Session;useuse Behat\Mink\Driver\GoutteDriver;
abstract classabstract class MinkTestCase extendsextends PHPUnit_Framework_TestCase{
privateprivate $session$session;
protected functionprotected function setUp(){
$this$this->session = newnew Session(newnew GoutteDriver);}
protected functionprotected function visit($url$url){
$this$this->session->visit($url$url);
returnreturn $this$this->session->getPage();}
}
![Page 7: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/7.jpg)
<?phpclassclass ApplicationTest extendsextends MinkTestCase{
public functionpublic function testExamplePageContainsExampleText(){
$page$page = $this$this->visit('http://example.com/');
$this$this->assertContains('Example Domain',$page$page->getContent()
);}
}
![Page 8: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/8.jpg)
$ phpunit ApplicationTestPHPUnit 4.1.1 by Sebastian Bergmann.
.
Time: 1.52 seconds, Memory: 6.75Mb
OK (1 test, 1 assertion)
![Page 9: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/9.jpg)
$ phpunit --testdox ApplicationTestPHPUnit 4.1.1 by Sebastian Bergmann.
Application[x] Example page contains example text
![Page 10: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/10.jpg)
# features/example.featureFeature: Example...
Scenario: Accessing an example web page worksGiven I am on "/"Then I should see "Example Domain"
![Page 11: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/11.jpg)
$ behat features/example.featureFeature: Example...
Scenario: Accessing an example web page worksGiven I am on "/"Then I should see "Example Domain"
1 scenario (1 passed)2 steps (2 passed)0m1.789s
![Page 12: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/12.jpg)
![Page 13: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/13.jpg)
![Page 14: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/14.jpg)
"[T]he Rails community has adopted the strategy of writing hoards of
cucumber tests that drive the application through the web server. This leads
to slow and fragile tests and breaks many of the rules of TDD which tries to
keep tests from coupling to unnecessary system components like the GUI."
— Robert C. Martin
![Page 15: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/15.jpg)
![Page 16: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/16.jpg)
<?phpnamespacenamespace Company\Project;
classclass Application{
public functionpublic function run(RequestInterface $request$request, ResponseInterface $response$response){
// ...}
}
![Page 17: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/17.jpg)
<?phpnamespacenamespace Company\Project;
interfaceinterface ResponseInterface{
public functionpublic function setData($key$key, $value$value);public functionpublic function getData($key$key);public functionpublic function hasData($key$key);
// ...}
![Page 18: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/18.jpg)
<?phpnamespacenamespace Company\Project\Tests;useuse Company\Project\Application;useuse Company\Project\Request;useuse Company\Project\Response;useuse PHPUnit_Framework_TestCase;
classclass HomepageTest extendsextends PHPUnit_Framework_TestCase{
protected functionprotected function setUp(){
$this$this->application = newnew Application;$this$this->request = newnew Request;$this$this->response = newnew Response;
}
public functionpublic function testHasNavigation(){
$this$this->application->run($this$this->request, $this$this->response);
$this$this->assertTrue($this$this->response->hasData('navigation'));}
}
![Page 19: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/19.jpg)
<?phpnamespacenamespace Company\Project\Tests;useuse Company\Project\Application;useuse Company\Project\Request;useuse Company\Project\Response;
classclass HomepageTest extendsextends IntegrationTestCase{
protected functionprotected function setUp(){
$this$this->application = newnew Application;$this$this->request = newnew Request;$this$this->response = newnew Response;
}
public functionpublic function testHasNavigation(){
$this$this->application->run($this$this->request, $this$this->response);
$this$this->assertResponseHasData('navigation', $this$this->response);}
}
![Page 20: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/20.jpg)
<?phpnamespacenamespace Company\Project\Tests;useuse Company\Project\ResponseInterface;useuse PHPUnit_Framework_TestCase;
abstract classabstract class IntegrationTestCase extendsextends PHPUnit_Framework_TestCase{
public functionpublic function assertResponseHasData($name$name, ResponseInterface $response$response){
$constraint$constraint = newnew DataExistsConstraint($response$response);$this$this->assertThat($name$name, $constraint$constraint);
}
public functionpublic function assertResponseNotHasData($name$name, ResponseInterface $response$response){
$constraint$constraint = newnew DataExistsConstraint($response$response);$this$this->assertThat($name$name, $this$this->logicalNot($constraint$constraint));
}}
![Page 21: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/21.jpg)
<?phpnamespacenamespace Company\Project\Tests;useuse Company\Project\ResponseInterface;useuse PHPUnit_Framework_Constraint;
classclass DataExistsConstraint extendsextends PHPUnit_Framework_Constraint{
privateprivate $response$response;
public functionpublic function __construct(ResponseInterface $response$response){
$this$this->response = $response$response;}
protected functionprotected function matches($other$other){
returnreturn $this$this->response->hasData($other$other);}
public functionpublic function toString(){
returnreturn 'data exists';}
}
![Page 22: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/22.jpg)
![Page 23: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/23.jpg)
<?phpnamespacenamespace Company\Project;
classclass SampleWorkflow{
privateprivate $backend$backend;privateprivate $service$service;
public functionpublic function __construct(Backend $backend$backend, Service $service$service){
$this$this->backend = $backend$backend;$this$this->service = $service$service;
}
public functionpublic function execute(Request $request$request){
$this$this->service->doWork($this$this->backend->getObjectById($request$request->getValue('id'))
);}
}
![Page 24: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/24.jpg)
<?phpnamespacenamespace Company\Project;useuse PHPUnit_Framework_TestCase;
classclass SampleWorkflowTest extendsextends PHPUnit_Framework_TestCase{
public functionpublic function testServiceCallUpdatesObject(){
$service$service = $this$this->getMockBuilder('Service')->enableProxyingToOriginalMethods()->getMock();
$service$service->expects($this$this->once())->method('doWork');
$backend$backend = newnew Backend;$workflow$workflow = newnew SampleWorkflow($backend$backend, $service$service);
$workflow$workflow->execute(newnew Request(arrayarray('id' => 2204)));}
}
![Page 25: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/25.jpg)
![Page 26: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/26.jpg)
![Page 27: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/27.jpg)
Domain Logic"Responsible for representing concepts of the business, information about
the business situation, and business rules. State that reflects the business
situation is controlled and used here, even though the technical details of
storing it are delegated to the infrastructure. This layer is the heart of
business software."
— Eric Evans
![Page 28: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/28.jpg)
Domain LogicWhen you cannot test your domain logic, the heart of your software, using
unit tests and in isolation from persistence and the web context ...
![Page 29: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/29.jpg)
![Page 30: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/30.jpg)
TDD is dead. Long live testing."I rarely unit test in the traditional sense of the word, where all
dependencies are mocked out, and thousands of tests can close in seconds.
It just hasn't been a useful way of dealing with the testing of Rails
applications. I test active record models directly, letting them hit the
database, and through the use of fixtures. Then layered on top is currently a
set of controller tests, but I'd much rather replace those with even higher
level system tests through Capybara or similar."
— David Heinemeier Hansson
![Page 31: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/31.jpg)
Monogamous TDD"If you trust those integration tests so much that you are willing to deploy
when they pass; and if they execute so quickly that you can continuously
and effectively refactor and clean the code, then you aren't doing any better
than me. Do it."
— Robert C. Martin
![Page 32: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/32.jpg)
Monogamous TDD"But (and this is a big "but"), it seems to me that integration tests have very
little chance of meeting my two predicates."
— Robert C. Martin
![Page 33: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/33.jpg)
![Page 34: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/34.jpg)
Effective Testing
— Rich Martin
» A high-fidelity test is one which is very sensitive to defects in the codeunder test
» A resilient test is one that only fails when a breaking change is made to thecode under test
» A high-precision test tells you exactly where the defect lies
![Page 35: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/35.jpg)
External and Internal Quality"Running end-to-end tests tells us about the the external quality of our
system, and writing them tells us something about how well we [...]
understand the domain, but end-to-end tests don't tell us how well we've
written the code. Writing unit tests gives us a lot of feedback about the
quality of our code, and running them tell us that we haven't broken any
classes [...]"
— Steve Freeman and Nat Pryce
![Page 36: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/36.jpg)
![Page 37: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/37.jpg)
talks.thePHP.cc
@s_bergmann
![Page 38: Why, What, and How: Testing in 2014 · Web Application » Presentation (Presentation Model, View, Template) » Application Logic (HTTP Abstraction, Routing, Controller) » Domain](https://reader035.vdocuments.net/reader035/viewer/2022071015/5fcd9b372256186c976a815a/html5/thumbnails/38.jpg)
sharing experience