![Page 1: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/1.jpg)
@asgrim
Crafting Quality PHP Applications: an overview
James TitcumbPHPSW 2018 meetup
![Page 2: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/2.jpg)
$ whoami
James Titcumb
www.jamestitcumb.com
www.roave.com
@asgrim
![Page 3: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/3.jpg)
@asgrim
![Page 4: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/4.jpg)
@asgrim
What is “quality”?
![Page 5: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/5.jpg)
@asgrimphoto: Rob Allen https://flic.kr/p/qmGpsq
![Page 6: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/6.jpg)
@asgrimphoto: https://goo.gl/QHWXQL
![Page 7: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/7.jpg)
@asgrimphoto: Rob Allen https://flic.kr/p/ecFbH8
![Page 8: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/8.jpg)
@asgrim
Quality.
![Page 9: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/9.jpg)
@asgrim
"The best code is no code at all”-- Jeff Atwood
source: https://blog.codinghorror.com/the-best-code-is-no-code-at-all/
![Page 10: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/10.jpg)
@asgrim
Trade-offs.
![Page 11: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/11.jpg)
@asgrim
Prototyping & short-lived apps/sites
![Page 12: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/12.jpg)
@asgrim
ProductsLong-lived projects. Open source software.
![Page 13: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/13.jpg)
@asgrim
What is quality in applications?
![Page 14: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/14.jpg)
@asgrim
What about time/cost…?
![Page 15: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/15.jpg)
@asgrim
“A freelancer at $25 an hour for 100 hours still costs more than a freelancer at $150 an hour that
takes 10 hours to do the same task”-- Brandon Savage
source: http://www.brandonsavage.net/earning-more-money-as-a-php-freelancer/
![Page 16: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/16.jpg)
@asgrim
Get an expert in.
![Page 17: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/17.jpg)
@asgrim
Complexity
![Page 18: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/18.jpg)
@asgrim
Processes
![Page 19: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/19.jpg)
@asgrim
This talk...
● Planning● Development● Testing● Continuous integration● Code reviews● Deployments
![Page 20: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/20.jpg)
@asgrim
Planning
![Page 21: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/21.jpg)
@asgrim
Planning is communication
![Page 22: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/22.jpg)
@asgrim
Use business terminology
![Page 23: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/23.jpg)
@asgrim
Explore and discover
![Page 24: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/24.jpg)
@asgrim
Build a model of the business
![Page 25: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/25.jpg)
@asgrim
![Page 26: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/26.jpg)
@asgrim
![Page 27: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/27.jpg)
@asgrim
The model must be fluid.
![Page 28: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/28.jpg)
@asgrim
Development
![Page 29: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/29.jpg)
@asgrim
Care about code
![Page 30: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/30.jpg)
@asgrim
“There are only two hard things in Computer Science: cache invalidation and naming things.”
-- Phil Karlton
source: https://martinfowler.com/bliki/TwoHardThings.html
![Page 31: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/31.jpg)
@asgrim
SimpleBeanFactoryAwareAspectInstanceFactory
![Page 32: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/32.jpg)
@asgrim
Loader
![Page 33: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/33.jpg)
@asgrim
Describe intent
![Page 34: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/34.jpg)
@asgrim
“Give awkward names to awkward concepts”-- Eric Evans
source: https://skillsmatter.com/conferences/8231-ddd-exchange-2017
![Page 35: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/35.jpg)
@asgrim
SOLID
![Page 36: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/36.jpg)
@asgrim
KISS
![Page 37: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/37.jpg)
@asgrim
Object Calisthenics
![Page 38: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/38.jpg)
@asgrim
Avoid early abstraction
![Page 39: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/39.jpg)
@asgrim
“Code for your use-case,not for your re-use-case”
-- Marco Pivetta
source: https://ocramius.github.io/extremely-defensive-php/#/39
![Page 40: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/40.jpg)
@asgrim
Care about your API
![Page 41: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/41.jpg)
@asgrim
A public method is like a child:once you've written it,
you are going to maintain itfor the rest of its life!
-- Stefan Priebsch
![Page 42: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/42.jpg)
@asgrim
Strict type declarations.Use declare(strict_types=1); by default
![Page 43: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/43.jpg)
@asgrim
Immutable value objects
declare(strict_types=1);use Assert\Assertion; // beberlei/assert library !final class PostalCode{ private const VALIDATION_EXPRESSION = '(GIR 0AA)|((([A-Z-[QVX]][0-9][0-... /** @var string */ private $value; public function __construct(string $value) { $this->assertValidPostalCode($value); $this->value = $value; } private function assertValidPostalCode(string $value) : string { Assertion::regex($value, self::VALIDATION_EXPRESSION); } public function __toString() : string { return $this->value; }}
![Page 44: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/44.jpg)
@asgrim
Value objects are valid!
declare(strict_types=1);
final class Thing { public function assignPostalCode(PostalCode $postalCode) : void { // ... we can trust $postalCode is a valid postal code }}
// 12345 is not valid - EXCEPTION!$myThing->assignPostalCode(new PostalCode('12345'));
// assignPostalCode is happy$myThing->assignPostalCode(new PostalCode('PO1 1AA'));
// With STRICT types, this will also FAIL$myThing->assignPostalCode(new PostalCode(12345));
![Page 45: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/45.jpg)
@asgrim
Testing
![Page 46: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/46.jpg)
@asgrim
Testing is NOT a separate line item
![Page 47: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/47.jpg)
@asgrim
Testing should be an assumption
![Page 48: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/48.jpg)
@asgrim
You’re already testing.
![Page 49: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/49.jpg)
@asgrim
Still need convincing?
![Page 50: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/50.jpg)
@asgrim
How?
![Page 51: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/51.jpg)
@asgrim
Reduce complexity
![Page 52: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/52.jpg)
@asgrim
Reduce complexity
public function process(Stuff a, string b, int c) : MoreStuff{ // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code // lots of complicated code
![Page 53: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/53.jpg)
@asgrim
Reduce complexity
public function meaningfulThing(Stuff a, string b, int c) : More{ // call nicer, meaningful methods below}
private function throwStuffIntoFire(Stuff a) : Fire{ // smaller, meaningful chunk of code}
private function combineStringWithFire(Fire a, string b) : string{ // simple, lovely code!}
private function postFlowersToSpain(int c) : void
![Page 54: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/54.jpg)
@asgrim
More complexity = more tests
![Page 55: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/55.jpg)
@asgrim
Test coverage
![Page 56: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/56.jpg)
@asgrim
Line coverage
<?phpfunction foo(bool $a, bool $b) { if ($a) { echo "A"; } if ($b) { echo "B"; }}
// generate coverage using calls:foo(true, false);foo(false, true);
![Page 57: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/57.jpg)
@asgrim
Line coverage
<?phpfunction foo(bool $a, bool $b) { if ($a) { echo "A"; } if ($b) { echo "B"; }}
// generate coverage using calls:foo(true, false);foo(false, true);
![Page 58: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/58.jpg)
@asgrim
Branch coverage
<?phpfunction foo(bool $a, bool $b) { if ($a) { echo "A"; } if ($b) { echo "B"; }}
// generate coverage using calls:foo(true, false);foo(false, true);
![Page 59: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/59.jpg)
@asgrim
Branch coverage
<?phpfunction foo(bool $a, bool $b) { if ($a) { echo "A"; } if ($b) { echo "B"; }}
// generate coverage using calls:foo(true, false);foo(false, true);
![Page 60: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/60.jpg)
@asgrim
Branch coverage
<?phpfunction foo(bool $a, bool $b) { if ($a) { echo "A"; } if ($b) { echo "B"; }}
// generate coverage using calls:foo(true, false);foo(false, true);foo(false, false); // NEW TEST!!!
![Page 61: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/61.jpg)
@asgrim
Branch coverage
<?phpfunction foo(bool $a, bool $b) { if ($a) { echo "A"; } if ($b) { echo "B"; }}
// generate coverage using calls:foo(true, false);foo(false, true);foo(false, false); // NEW TEST!!!foo(true, true); // NEW TEST!!!
![Page 62: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/62.jpg)
@asgrim
Prevent coverage leaking
![Page 63: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/63.jpg)
@asgrim
Prevent coverage leaking
<?php
namespace Foo;
/** * @covers \Foo\Bar */final class BarTest extends TestCase{ // write some tests!}
![Page 64: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/64.jpg)
@asgrim
Are the tests testing?
![Page 65: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/65.jpg)
@asgrim
Example of a test not testing…
public function testPurchaseTickets(){ $event = Event::create(uniq('event', true) $customer = Customer::create(uniq('name', true)); $shop->purchaseTicket(1, $event, [$customer]);}
@asgrim
![Page 66: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/66.jpg)
@asgrim
Assert you’re asserting
public function testPurchaseTickets(){ $event = Event::create(uniq('event', true) $customer = Customer::create(uniq('name', true)); $receipt = $shop->purchaseTicket(1, $event, [$customer]);
self::assertSame($event, $receipt->event()); $customersInReceipt = $receipt->customers(); self::assertCount(1, $customersInReceipt); self::assertContains($customer, $customersInReceipt);}
@asgrim
![Page 67: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/67.jpg)
@asgrim
Test the tests are testing!
![Page 68: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/68.jpg)
@asgrim
Mutation testing
function add(int $a, int $b) : int {
return $a + $b;
}
function testAdd() {
$result = add(2, 3);
// self::assertSame(5, $result);
}
![Page 69: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/69.jpg)
@asgrim
Mutation testing
function add(int $a, int $b) : int {
return $a - $b;
}
function testAdd() {
$result = add(2, 3);
// self::assertSame(5, $result);
}
![Page 70: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/70.jpg)
@asgrim
Mutation testing
function add(int $a, int $b) : int {
return $a - $b;
}
function testAdd() {
$result = add(2, 3);
self::assertSame(5, $result);
// /\/\/\ test will now fail with mutation
}
![Page 71: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/71.jpg)
@asgrim
What about other tests?
![Page 72: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/72.jpg)
@asgrim
Integration tests
![Page 73: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/73.jpg)
@asgrim
Behaviour tests
![Page 74: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/74.jpg)
@asgrim
BAD! Do not do this.
Feature: Ability to print my boarding pass
Scenario: A checked in passenger can print their boarding pass Given I have a flight booked And I have checked in When I visit the home page And I click the ".manage-booking" button And I enter "CJM23L" in the ".bref-ipt-fld" field And I click the "Find Booking" button Then I should see the ".booking-ref.print" button When I click the ".booking-ref.print" button Then I should see the print dialogue
![Page 75: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/75.jpg)
@asgrim
Better Behaviour test
Feature: Ability to print my boarding pass
Policies: - Boarding passes are only available when already checked in - If customer cannot print boarding pass, they can collect at The airport - more business rules etc...
Scenario: A checked in passenger can print their boarding pass Given I have a flight booked for LHR-OTP on 24th May And I have previously checked in for the flight When I display my booking reference "CJM23L" Then I should be able to print my boarding pass And the boarding pass should display flight details correctly
![Page 76: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/76.jpg)
@asgrim
Why is this important?
![Page 77: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/77.jpg)
@asgrim
Automate these tests
![Page 78: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/78.jpg)
@asgrim
Automated tests
Application (and UI, API, etc.)
Domain / Business Logic
Infrastructure (DBAL, APIs, etc.)
![Page 79: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/79.jpg)
@asgrim
Automated tests
Application (and UI, API, etc.)
Domain / Business Logic
Infrastructure (DBAL, APIs, etc.)
![Page 80: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/80.jpg)
@asgrim
Testing at domain layer
Application (UI, API, etc.)
Domain / Business Logic
Infrastructure (DB, APIs, etc.)
// Testing via the UIpublic function iDisplayMyBookingReference(string $reference){ $page = $this->getSession()->getPage(); $page->click(".manage-booking"); $page->findField(".bref-ipt-fld")->setValue($reference); $page->click("Find Booking");}
// Using the domain layer directly in testspublic function iDisplayMyBookingReference(string $reference){ $this->booking = $this->retrieveBooking($reference);}
![Page 81: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/81.jpg)
@asgrim
Some UI testing is okay!!!
Feature: Ability to print my boarding pass
Policies: - Boarding passes are only available when already checked in - If customer cannot print boarding pass, they can collect at The airport - more business rules etc...
@ui Scenario: A checked in passenger can print their boarding pass Given I have a flight booked for LHR-OTP on 24th May And I have previously checked in for the flight When I display my booking reference "CJM23L" Then I should be able to print my boarding pass And the boarding pass should display flight details correctly
![Page 82: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/82.jpg)
@asgrim
Automate all the things!
![Page 83: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/83.jpg)
@asgrim
Continuous Integration
![Page 84: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/84.jpg)
@asgrim
Tests cost money to run(manually)
![Page 85: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/85.jpg)
@asgrim
Travis-CI.com
![Page 86: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/86.jpg)
@asgrim
Jenkins
![Page 87: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/87.jpg)
@asgrim
What to automate?
![Page 88: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/88.jpg)
@asgrim
The goal?
![Page 89: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/89.jpg)
@asgrim
Code reviews
![Page 90: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/90.jpg)
@asgrim
What to look for in code review?
![Page 91: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/91.jpg)
@asgrim
What to look for in code review?Code style.
![Page 92: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/92.jpg)
@asgrim
What to look for in code review?Small, atomic changes.
![Page 93: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/93.jpg)
@asgrim
What to look for in code review?Composer versions.
![Page 94: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/94.jpg)
@asgrim
What to look for in code review?Structure & good practices.
![Page 95: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/95.jpg)
@asgrim
What to look for in code review?Tests.
![Page 96: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/96.jpg)
@asgrim
What to look for in code review?Documentation.
![Page 97: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/97.jpg)
@asgrim
What to look for in code review?Security.
![Page 98: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/98.jpg)
@asgrim
What to look for in code review?Insight.
![Page 99: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/99.jpg)
@asgrim
It takes practice.
![Page 100: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/100.jpg)
@asgrim
Deployments
![Page 101: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/101.jpg)
@asgrim
Automate deployments!
![Page 102: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/102.jpg)
@asgrim
One-click deployments
![Page 103: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/103.jpg)
@asgrim
“Move fast and break things”-- a stupid Facebook mantra
![Page 104: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/104.jpg)
@asgrim
“Move fast and break things with stable infra”-- Facebook mantra since 2014
![Page 105: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/105.jpg)
@asgrim
Continuous Delivery & Deployment
![Page 106: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/106.jpg)
@asgrim
Better quality
![Page 107: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/107.jpg)
@asgrim
Better quality = Higher confidence
![Page 108: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/108.jpg)
@asgrim
Better quality = Higher confidence = Happy customers
![Page 109: Crafting Quality PHP Applications: an overview (PHPSW March 2018)](https://reader031.vdocuments.site/reader031/viewer/2022022419/5aad681f7f8b9a3a238b4893/html5/thumbnails/109.jpg)
Any questions?
https://joind.in/talk/96cee
James Titcumb@asgrim