Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TDD anti patterns - episode 6 - with Ignacio Saporitti and Pablo Díaz

TDD anti patterns - episode 6 - with Ignacio Saporitti and Pablo Díaz

In this talk we are going to introduce two new TDD anti-patterns that came in our experience practicing TDD in different projects: The jumper and The flash.

Marabesi

May 26, 2022
Tweet

More Decks by Marabesi

Other Decks in Programming

Transcript

  1. TDD - EP 6
    codurance.com
    Testing anti-patterns - The One, The
    Peeping Tom, The jumper and The flash

    View full-size slide

  2. Matheus Marabesi
    Hello there, you can call me Marabesi,
    But my name is Matheus Marabesi, I work at Codurance as a
    Software Craftsperson.
    I enjoy talking about anything related to: testing, patterns and
    gamification.
    You can find me at @MatheusMarabesi or https://marabesi.com
    Codurance
    Crafting Code

    View full-size slide

  3. 1. Intro - Recap
    2. The One
    3. The Peeping Tom
    4. The Flash
    5. The Jumper
    6. Wrapping up
    Crafting code
    Agenda

    View full-size slide

  4. 1. Intro - Recap
    2. The One
    3. The Peeping Tom
    4. The Flash
    5. The Jumper
    6. Wrapping up
    Crafting code
    Agenda

    View full-size slide

  5. 1. Recap
    Episode 1, Episode 2, Episode 3,
    Episode 4, Episode 5
    Getting started

    View full-size slide

  6. The Liar
    The Giant
    The Mockery
    The Inspector
    Generous Leftovers
    The Local Hero
    The Nitpicker
    The Secret Catcher
    The Dodger
    The Loudmouth
    Anti patterns
    The Greedy Catcher
    Excessive Setup
    The Sequencer
    Hidden Dependency
    The Enumerator
    The Stranger
    The Operating System Evangelist
    Success Against All Odds
    The Free Ride
    The One
    The Peeping Tom
    The Slow Poke
    James Carr - TDD Anti-Patterns

    View full-size slide

  7. The Liar 4
    The Giant 5
    The Mockery 1
    The Inspector 7
    Generous Leftovers 5
    The Local Hero 7
    The Nitpicker 8
    The Secret Catcher 7
    The Dodger 8
    The Loudmouth 8
    Anti patterns
    The Greedy Catcher 7
    Excessive Setup 3
    The Sequencer 7
    Hidden Dependency 2
    The Enumerator 8
    The Stranger 7
    The Operating System Evangelist 8
    Success Against All Odds 5
    The Free Ride 8
    The One 7
    The Peeping Tom 7
    The Slow Poke 6

    View full-size slide

  8. Anti patterns - Survey takeaways
    1. Survey notes: Javascript, PHP and Java were the most used programming languages
    2. Survey notes: Practitioners usually informally learn TDD
    3. The anti patterns covered were related to test last
    4. Subjects we touched around testability: SOLID, Object calisthenics, Non-determinism and the
    test pyramid
    5. Examples are from open source projects and also extraction from real code bases

    View full-size slide

  9. MOST POPULAR

    View full-size slide

  10. MOST POPULAR

    View full-size slide

  11. 2. Anti-patterns - Episode 6
    The One, The Peeping Tom, The jumper
    and The flash
    Getting started

    View full-size slide

  12. The Liar
    The Giant
    The Mockery
    The Inspector
    Generous Leftovers
    The Local Hero
    The Nitpicker
    The Secret Catcher
    The Dodger
    The Loudmouth
    Anti patterns
    The Greedy Catcher
    Excessive Setup
    The Sequencer
    Hidden Dependency
    The Enumerator
    The Stranger
    The Operating System Evangelist
    Success Against All Odds
    The Free Ride
    The One
    The Peeping Tom
    The Slow Poke
    James Carr - TDD Anti-Patterns

    View full-size slide

  13. The Liar 4
    The Giant 5
    The Mockery 1
    The Inspector 7
    Generous Leftovers 5
    The Local Hero 7
    The Nitpicker 8
    The Secret Catcher 7
    The Dodger 8
    The Loudmouth 8
    Anti patterns
    The Greedy Catcher 7
    Excessive Setup 3
    The Sequencer 7
    Hidden Dependency 2
    The Enumerator 8
    The Stranger 7
    The Operating System Evangelist 8
    Success Against All Odds 5
    The Free Ride 8
    The One 7
    The Peeping Tom 7
    The Slow Poke 6

    View full-size slide

  14. 2. The One - 🏆 7
    Crafting code

    View full-size slide

  15. 2. The One - 🏆 7
    A combination of several patterns, particularly
    TheFreeRide and TheGiant, a unit test that
    contains only one test method which tests the
    entire set of functionality an object has. A
    common indicator is that the test method is often
    the same as the unit test name, and contains
    multiple lines of setup and assertions.
    Crafting code

    View full-size slide

  16. 2. The One - 🏆 7
    A combination of several patterns, particularly
    TheFreeRide and TheGiant, a unit test that
    contains only one test method which tests the
    entire set of functionality an object has. A
    common indicator is that the test method is often
    the same as the unit test name, and contains
    multiple lines of setup and assertions.
    Crafting code

    View full-size slide

  17. 2. The One - 🏆 7
    A combination of several patterns, particularly
    TheFreeRide and TheGiant, a unit test that
    contains only one test method which tests the
    entire set of functionality an object has. A
    common indicator is that the test method is often
    the same as the unit test name, and contains
    multiple lines of setup and assertions.
    Crafting code

    View full-size slide

  18. The giant
    A unit test that, although it is validly
    testing the object under test, can span
    thousands of lines and contain many
    many test cases. This can be an indicator
    that the system under tests is a
    God Object.
    Crafting code

    View full-size slide

  19. namespace PhpOffice\PhpWord\Shared;
    class ConverterTest extends \PHPUnit\Framework\TestCase
    {
    public function testUnitConversions()
    {
    $values = array();
    $values[] = 0; // zero value
    $values[] = rand(1, 100) / 100; // fraction number
    $values[] = rand(1, 100); // integer
    foreach ($values as $value) {
    $result = Converter::cmToTwip($value);
    $this->assertEquals($value / 2.54 * 1440, $result);
    $result = Converter::cmToInch($value);
    $this->assertEquals($value / 2.54, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  20. namespace PhpOffice\PhpWord\Shared;
    class ConverterTest extends \PHPUnit\Framework\TestCase
    {
    public function testUnitConversions()
    {
    $values = array();
    $values[] = 0; // zero value
    $values[] = rand(1, 100) / 100; // fraction number
    $values[] = rand(1, 100); // integer
    foreach ($values as $value) {
    $result = Converter::cmToTwip($value);
    $this->assertEquals($value / 2.54 * 1440, $result);
    $result = Converter::cmToInch($value);
    $this->assertEquals($value / 2.54, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  21. namespace PhpOffice\PhpWord\Shared;
    class ConverterTest extends \PHPUnit\Framework\TestCase
    {
    public function testUnitConversions()
    {
    $values = array();
    $values[] = 0; // zero value
    $values[] = rand(1, 100) / 100; // fraction number
    $values[] = rand(1, 100); // integer
    foreach ($values as $value) {
    $result = Converter::cmToTwip($value);
    $this->assertEquals($value / 2.54 * 1440, $result);
    $result = Converter::cmToInch($value);
    $this->assertEquals($value / 2.54, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  22. namespace PhpOffice\PhpWord\Shared;
    class ConverterTest extends \PHPUnit\Framework\TestCase
    {
    public function testUnitConversions()
    {
    $values = array();
    $values[] = 0; // zero value
    $values[] = rand(1, 100) / 100; // fraction number
    $values[] = rand(1, 100); // integer
    foreach ($values as $value) {
    $result = Converter::cmToTwip($value);
    $this->assertEquals($value / 2.54 * 1440, $result);
    $result = Converter::cmToInch($value);
    $this->assertEquals($value / 2.54, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  23. namespace PhpOffice\PhpWord\Shared;
    class ConverterTest extends \PHPUnit\Framework\TestCase
    {
    public function testUnitConversions()
    {
    $values = array();
    $values[] = 0; // zero value
    $values[] = rand(1, 100) / 100; // fraction number
    $values[] = rand(1, 100); // integer
    foreach ($values as $value) {
    $result = Converter::cmToTwip($value);
    $this->assertEquals($value / 2.54 * 1440, $result);
    $result = Converter::cmToInch($value);
    $this->assertEquals($value / 2.54, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  24. $result = Converter::cmToPixel($value);
    $this->assertEquals($value / 2.54 * 96, $result);
    $result = Converter::cmToPoint($value);
    $this->assertEquals($value / 2.54 * 72, $result);
    $result = Converter::cmToEmu($value);
    $this->assertEquals(round($value / 2.54 * 96 * 9525), $result);
    $result = Converter::inchToTwip($value);
    $this->assertEquals($value * 1440, $result);
    $result = Converter::inchToCm($value);
    $this->assertEquals($value * 2.54, $result);
    $result = Converter::inchToPixel($value);
    $this->assertEquals($value * 96, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  25. $result = Converter::cmToPixel($value);
    $this->assertEquals($value / 2.54 * 96, $result);
    $result = Converter::cmToPoint($value);
    $this->assertEquals($value / 2.54 * 72, $result);
    $result = Converter::cmToEmu($value);
    $this->assertEquals(round($value / 2.54 * 96 * 9525), $result);
    $result = Converter::inchToTwip($value);
    $this->assertEquals($value * 1440, $result);
    $result = Converter::inchToCm($value);
    $this->assertEquals($value * 2.54, $result);
    $result = Converter::inchToPixel($value);
    $this->assertEquals($value * 96, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  26. $result = Converter::cmToPixel($value);
    $this->assertEquals($value / 2.54 * 96, $result);
    $result = Converter::cmToPoint($value);
    $this->assertEquals($value / 2.54 * 72, $result);
    $result = Converter::cmToEmu($value);
    $this->assertEquals(round($value / 2.54 * 96 * 9525), $result);
    $result = Converter::inchToTwip($value);
    $this->assertEquals($value * 1440, $result);
    $result = Converter::inchToCm($value);
    $this->assertEquals($value * 2.54, $result);
    $result = Converter::inchToPixel($value);
    $this->assertEquals($value * 96, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  27. $result = Converter::cmToPixel($value);
    $this->assertEquals($value / 2.54 * 96, $result);
    $result = Converter::cmToPoint($value);
    $this->assertEquals($value / 2.54 * 72, $result);
    $result = Converter::cmToEmu($value);
    $this->assertEquals(round($value / 2.54 * 96 * 9525), $result);
    $result = Converter::inchToTwip($value);
    $this->assertEquals($value * 1440, $result);
    $result = Converter::inchToCm($value);
    $this->assertEquals($value * 2.54, $result);
    $result = Converter::inchToPixel($value);
    $this->assertEquals($value * 96, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  28. $result = Converter::cmToPixel($value);
    $this->assertEquals($value / 2.54 * 96, $result);
    $result = Converter::cmToPoint($value);
    $this->assertEquals($value / 2.54 * 72, $result);
    $result = Converter::cmToEmu($value);
    $this->assertEquals(round($value / 2.54 * 96 * 9525), $result);
    $result = Converter::inchToTwip($value);
    $this->assertEquals($value * 1440, $result);
    $result = Converter::inchToCm($value);
    $this->assertEquals($value * 2.54, $result);
    $result = Converter::inchToPixel($value);
    $this->assertEquals($value * 96, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  29. $result = Converter::cmToPixel($value);
    $this->assertEquals($value / 2.54 * 96, $result);
    $result = Converter::cmToPoint($value);
    $this->assertEquals($value / 2.54 * 72, $result);
    $result = Converter::cmToEmu($value);
    $this->assertEquals(round($value / 2.54 * 96 * 9525), $result);
    $result = Converter::inchToTwip($value);
    $this->assertEquals($value * 1440, $result);
    $result = Converter::inchToCm($value);
    $this->assertEquals($value * 2.54, $result);
    $result = Converter::inchToPixel($value);
    $this->assertEquals($value * 96, $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  30. $result = Converter::inchToPoint($value);
    $this->assertEquals($value * 72, $result);
    $result = Converter::inchToEmu($value);
    $this->assertEquals(round($value * 96 * 9525), $result);
    $result = Converter::pixelToTwip($value);
    $this->assertEquals($value / 96 * 1440, $result);
    $result = Converter::pixelToCm($value);
    $this->assertEquals($value / 96 * 2.54, $result);
    $result = Converter::pixelToPoint($value);
    $this->assertEquals($value / 96 * 72, $result);
    $result = Converter::pixelToEmu($value);
    $this->assertEquals(round($value * 9525), $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  31. $result = Converter::inchToPoint($value);
    $this->assertEquals($value * 72, $result);
    $result = Converter::inchToEmu($value);
    $this->assertEquals(round($value * 96 * 9525), $result);
    $result = Converter::pixelToTwip($value);
    $this->assertEquals($value / 96 * 1440, $result);
    $result = Converter::pixelToCm($value);
    $this->assertEquals($value / 96 * 2.54, $result);
    $result = Converter::pixelToPoint($value);
    $this->assertEquals($value / 96 * 72, $result);
    $result = Converter::pixelToEmu($value);
    $this->assertEquals(round($value * 9525), $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  32. $result = Converter::inchToPoint($value);
    $this->assertEquals($value * 72, $result);
    $result = Converter::inchToEmu($value);
    $this->assertEquals(round($value * 96 * 9525), $result);
    $result = Converter::pixelToTwip($value);
    $this->assertEquals($value / 96 * 1440, $result);
    $result = Converter::pixelToCm($value);
    $this->assertEquals($value / 96 * 2.54, $result);
    $result = Converter::pixelToPoint($value);
    $this->assertEquals($value / 96 * 72, $result);
    $result = Converter::pixelToEmu($value);
    $this->assertEquals(round($value * 9525), $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  33. $result = Converter::inchToPoint($value);
    $this->assertEquals($value * 72, $result);
    $result = Converter::inchToEmu($value);
    $this->assertEquals(round($value * 96 * 9525), $result);
    $result = Converter::pixelToTwip($value);
    $this->assertEquals($value / 96 * 1440, $result);
    $result = Converter::pixelToCm($value);
    $this->assertEquals($value / 96 * 2.54, $result);
    $result = Converter::pixelToPoint($value);
    $this->assertEquals($value / 96 * 72, $result);
    $result = Converter::pixelToEmu($value);
    $this->assertEquals(round($value * 9525), $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  34. $result = Converter::inchToPoint($value);
    $this->assertEquals($value * 72, $result);
    $result = Converter::inchToEmu($value);
    $this->assertEquals(round($value * 96 * 9525), $result);
    $result = Converter::pixelToTwip($value);
    $this->assertEquals($value / 96 * 1440, $result);
    $result = Converter::pixelToCm($value);
    $this->assertEquals($value / 96 * 2.54, $result);
    $result = Converter::pixelToPoint($value);
    $this->assertEquals($value / 96 * 72, $result);
    $result = Converter::pixelToEmu($value);
    $this->assertEquals(round($value * 9525), $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  35. $result = Converter::inchToPoint($value);
    $this->assertEquals($value * 72, $result);
    $result = Converter::inchToEmu($value);
    $this->assertEquals(round($value * 96 * 9525), $result);
    $result = Converter::pixelToTwip($value);
    $this->assertEquals($value / 96 * 1440, $result);
    $result = Converter::pixelToCm($value);
    $this->assertEquals($value / 96 * 2.54, $result);
    $result = Converter::pixelToPoint($value);
    $this->assertEquals($value / 96 * 72, $result);
    $result = Converter::pixelToEmu($value);
    $this->assertEquals(round($value * 9525), $result);
    PHPUnit - PHPOffice/Word

    View full-size slide

  36. $result = Converter::degreeToAngle($value);
    $this->assertEquals((int) round($value * 60000), $result);
    $result = Converter::angleToDegree($value);
    $this->assertEquals(round($value / 60000), $result);
    }
    }
    PHPUnit - PHPOffice/Word

    View full-size slide

  37. public void testFlightMileage_asKm2() throws Exception {
    // set up fixture
    // exercise constructor
    Flight newFlight = new Flight(validFlightNumber);
    // verify constructed object
    assertEquals(validFlightNumber, newFlight.number);
    assertEquals("", newFlight.airlineCode);
    assertNull(newFlight.airline);
    // set up mileage
    newFlight.setMileage(1122);
    // exercise mileage translator
    int actualKilometres = newFlight.getMileageAsKm();
    // verify results
    int expectedKilometres = 1810;
    assertEquals( expectedKilometres, actualKilometres);
    // now try it with a canceled flight
    newFlight.cancel();
    try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    Assertion Roulette - xUnit

    View full-size slide

  38. public void testFlightMileage_asKm2() throws Exception {
    // set up fixture
    // exercise constructor
    Flight newFlight = new Flight(validFlightNumber);
    // verify constructed object
    assertEquals(validFlightNumber, newFlight.number);
    assertEquals("", newFlight.airlineCode);
    assertNull(newFlight.airline);
    // set up mileage
    newFlight.setMileage(1122);
    // exercise mileage translator
    int actualKilometres = newFlight.getMileageAsKm();
    // verify results
    int expectedKilometres = 1810;
    assertEquals( expectedKilometres, actualKilometres);
    // now try it with a canceled flight
    newFlight.cancel();
    try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    Assertion Roulette - xUnit

    View full-size slide

  39. public void testFlightMileage_asKm2() throws Exception {
    // set up fixture
    // exercise constructor
    Flight newFlight = new Flight(validFlightNumber);
    // verify constructed object
    assertEquals(validFlightNumber, newFlight.number);
    assertEquals("", newFlight.airlineCode);
    assertNull(newFlight.airline);
    // set up mileage
    newFlight.setMileage(1122);
    // exercise mileage translator
    int actualKilometres = newFlight.getMileageAsKm();
    // verify results
    int expectedKilometres = 1810;
    assertEquals( expectedKilometres, actualKilometres);
    // now try it with a canceled flight
    newFlight.cancel();
    try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    Assertion Roulette - xUnit

    View full-size slide

  40. public void testFlightMileage_asKm2() throws Exception {
    // set up fixture
    // exercise constructor
    Flight newFlight = new Flight(validFlightNumber);
    // verify constructed object
    assertEquals(validFlightNumber, newFlight.number);
    assertEquals("", newFlight.airlineCode);
    assertNull(newFlight.airline);
    // set up mileage
    newFlight.setMileage(1122);
    // exercise mileage translator
    int actualKilometres = newFlight.getMileageAsKm();
    // verify results
    int expectedKilometres = 1810;
    assertEquals( expectedKilometres, actualKilometres);
    // now try it with a canceled flight
    newFlight.cancel();
    try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    Assertion Roulette - xUnit

    View full-size slide

  41. public void testFlightMileage_asKm2() throws Exception {
    // set up fixture
    // exercise constructor
    Flight newFlight = new Flight(validFlightNumber);
    // verify constructed object
    assertEquals(validFlightNumber, newFlight.number);
    assertEquals("", newFlight.airlineCode);
    assertNull(newFlight.airline);
    // set up mileage
    newFlight.setMileage(1122);
    // exercise mileage translator
    int actualKilometres = newFlight.getMileageAsKm();
    // verify results
    int expectedKilometres = 1810;
    assertEquals( expectedKilometres, actualKilometres);
    // now try it with a canceled flight
    newFlight.cancel();
    try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    Assertion Roulette - xUnit

    View full-size slide

  42. try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    e.getMessage());
    }
    }
    Assertion Roulette - xUnit

    View full-size slide

  43. try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    e.getMessage());
    }
    }
    Assertion Roulette - xUnit

    View full-size slide

  44. try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    e.getMessage());
    }
    }
    Assertion Roulette - xUnit

    View full-size slide

  45. try {
    newFlight.getMileageAsKm();
    fail("Expected exception");
    } catch (InvalidRequestException e) {
    assertEquals( "Cannot get cancelled flight mileage",
    e.getMessage());
    }
    }
    Assertion Roulette - xUnit

    View full-size slide

  46. The Free Ride
    Rather than write a new test case method to
    test another feature or functionality, a new
    assertion rides along in an existing test case.
    Crafting code

    View full-size slide

  47. public class ToolLocationTest {
    @Rule
    public JenkinsRule j = new JenkinsRule();
    @Test
    public void toolCompatibility() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    JDK[] jdk = j.jenkins.getDescriptorByType(JDK.DescriptorImpl.class).getInstallations();
    assertEquals(Arrays.asList(jdk), j.jenkins.getJDKs());
    assertEquals(2, jdk.length); // JenkinsRule adds a 'default' JDK
    assertEquals("default", jdk[1].getName()); // make sure it's really that we're seeing
    assertEquals("FOOBAR", jdk[0].getHome());
    Java - Jenkins

    View full-size slide

  48. public class ToolLocationTest {
    @Rule
    public JenkinsRule j = new JenkinsRule();
    @Test
    public void toolCompatibility() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    JDK[] jdk = j.jenkins.getDescriptorByType(JDK.DescriptorImpl.class).getInstallations();
    assertEquals(Arrays.asList(jdk), j.jenkins.getJDKs());
    assertEquals(2, jdk.length); // JenkinsRule adds a 'default' JDK
    assertEquals("default", jdk[1].getName()); // make sure it's really that we're seeing
    assertEquals("FOOBAR", jdk[0].getHome());
    Java - Jenkins

    View full-size slide

  49. public class ToolLocationTest {
    @Rule
    public JenkinsRule j = new JenkinsRule();
    @Test
    public void toolCompatibility() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    JDK[] jdk = j.jenkins.getDescriptorByType(JDK.DescriptorImpl.class).getInstallations();
    assertEquals(Arrays.asList(jdk), j.jenkins.getJDKs());
    assertEquals(2, jdk.length); // JenkinsRule adds a 'default' JDK
    assertEquals("default", jdk[1].getName()); // make sure it's really that we're seeing
    assertEquals("FOOBAR", jdk[0].getHome());
    Java - Jenkins

    View full-size slide

  50. public class ToolLocationTest {
    @Rule
    public JenkinsRule j = new JenkinsRule();
    @Test
    public void toolCompatibility() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    JDK[] jdk = j.jenkins.getDescriptorByType(JDK.DescriptorImpl.class).getInstallations();
    assertEquals(Arrays.asList(jdk), j.jenkins.getJDKs());
    assertEquals(2, jdk.length); // JenkinsRule adds a 'default' JDK
    assertEquals("default", jdk[1].getName()); // make sure it's really that we're seeing
    assertEquals("FOOBAR", jdk[0].getHome());
    Java - Jenkins

    View full-size slide

  51. public class ToolLocationTest {
    @Rule
    public JenkinsRule j = new JenkinsRule();
    @Test
    public void toolCompatibility() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    JDK[] jdk = j.jenkins.getDescriptorByType(JDK.DescriptorImpl.class).getInstallations();
    assertEquals(Arrays.asList(jdk), j.jenkins.getJDKs());
    assertEquals(2, jdk.length); // JenkinsRule adds a 'default' JDK
    assertEquals("default", jdk[1].getName()); // make sure it's really that we're seeing
    assertEquals("FOOBAR", jdk[0].getHome());
    Java - Jenkins

    View full-size slide

  52. The automation server

    View full-size slide

  53. public class ToolLocationTest {
    @Test
    @LocalData
    public void shouldBeCompatibleWithMaven() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    }
    @Test
    @LocalData
    public void shouldBeCompatibleWithAnt() {
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    }
    @Test
    @LocalData
    Java - Jenkins

    View full-size slide

  54. public class ToolLocationTest {
    @Test
    @LocalData
    public void shouldBeCompatibleWithMaven() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    }
    @Test
    @LocalData
    public void shouldBeCompatibleWithAnt() {
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    }
    @Test
    @LocalData
    Java - Jenkins

    View full-size slide

  55. public class ToolLocationTest {
    @Test
    @LocalData
    public void shouldBeCompatibleWithMaven() {
    Maven.MavenInstallation[] maven = j.jenkins.getDescriptorByType(Maven.DescriptorImpl.class).getInstallations();
    assertEquals(1, maven.length);
    assertEquals("bar", maven[0].getHome());
    assertEquals("Maven 1", maven[0].getName());
    }
    @Test
    @LocalData
    public void shouldBeCompatibleWithAnt() {
    Ant.AntInstallation[] ant = j.jenkins.getDescriptorByType(Ant.DescriptorImpl.class).getInstallations();
    assertEquals(1, ant.length);
    assertEquals("foo", ant[0].getHome());
    assertEquals("Ant 1", ant[0].getName());
    }
    @Test
    @LocalData
    Java - Jenkins

    View full-size slide

  56. @Test
    @LocalData
    public void shouldBeCompatibleWithJdk() {
    JDK[] jdk = j.jenkins.getDescriptorByType(JDK.DescriptorImpl.class).getInstallations();
    assertEquals(Arrays.asList(jdk), j.jenkins.getJDKs());
    assertEquals(2, jdk.length); // JenkinsRule adds a 'default' JDK
    assertEquals("default", jdk[1].getName()); // make sure it's really that we're seeing
    assertEquals("FOOBAR", jdk[0].getHome());
    assertEquals("FOOBAR", jdk[0].getJavaHome());
    assertEquals("1.6", jdk[0].getName());
    }
    }
    Java - Jenkins

    View full-size slide

  57. Web automation

    View full-size slide

  58. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  59. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  60. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  61. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  62. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  63. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  64. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  65. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  66. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  67. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  68. it('Page.Events.RequestFailed', async () => {
    const { page, server, isChrome } = getTestState();
    await page.setRequestInterception(true);
    page.on('request', (request) => {
    if (request.url().endsWith('css')) request.abort();
    else request.continue();
    });
    const failedRequests = [];
    page.on('requestfailed', (request) => failedRequests.push(request));
    await page.goto(server.PREFIX + '/one-style.html');
    expect(failedRequests.length).toBe(1);
    expect(failedRequests[0].url()).toContain('one-style.css');
    expect(failedRequests[0].response()).toBe(null);
    expect(failedRequests[0].resourceType()).toBe('stylesheet');
    if (isChrome)
    expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED');
    else
    expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE');
    expect(failedRequests[0].frame()).toBeTruthy();
    });
    Javascript/Typescript - Puppeteer

    View full-size slide

  69. 3. The Peeping Tom - 🏆7
    Crafting code

    View full-size slide

  70. 3. The Peeping Tom - 🏆7
    A test that, due to shared resources, can see the result data
    of another test, and may cause the test to fail even though
    the system under test is perfectly valid. This has been seen
    commonly in fitnesse, where the use of static member
    variables to hold collections aren’t properly cleaned after test
    execution, often popping up unexpectedly in other test runs.
    Also known as TheUninvitedGuests
    Crafting code

    View full-size slide

  71. 3. The Peeping Tom - 🏆7
    A test that, due to shared resources, can see the result data
    of another test, and may cause the test to fail even though
    the system under test is perfectly valid. This has been seen
    commonly in fitnesse, where the use of static member
    variables to hold collections aren’t properly cleaned after
    test execution, often popping up unexpectedly in other test
    runs. Also known as TheUninvitedGuests
    Crafting code

    View full-size slide

  72. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  73. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  74. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  75. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  76. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  77. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  78. public class MySingleton{
    private static MySingleton instance;
    private String property;
    private MySingleton(String property) {
    this.property = property;
    }
    public static synchronized MySingleton getInstance() {
    if (instance == null) {
    instance = new MySingleton(System.getProperty("com.example"));
    }
    return instance;
    }
    public Object getSomething() {
    return this.property;
    }
    }
    Java - Singleton

    View full-size slide

  79. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  80. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  81. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  82. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  83. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  84. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  85. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  86. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  87. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  88. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  89. class MySingletonTest {
    @BeforeEach
    public void resetSingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
    IllegalAccessException {
    Field instance = MySingleton.class.getDeclaredField("instance");
    instance.setAccessible(true);
    instance.set(null, null);
    }
    }
    Java - Singleton

    View full-size slide

  90. class MySingletonTest {
    @BeforeEach
    public void resetSingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
    IllegalAccessException {
    Field instance = MySingleton.class.getDeclaredField("instance");
    instance.setAccessible(true);
    instance.set(null, null);
    }
    }
    Java - Singleton

    View full-size slide

  91. class MySingletonTest {
    @BeforeEach
    public void resetSingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
    IllegalAccessException {
    Field instance = MySingleton.class.getDeclaredField("instance");
    instance.setAccessible(true);
    instance.set(null, null);
    }
    }
    Java - Singleton

    View full-size slide

  92. class MySingletonTest {
    @BeforeEach
    public void resetSingleton() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
    IllegalAccessException {
    Field instance = MySingleton.class.getDeclaredField("instance");
    instance.setAccessible(true);
    instance.set(null, null);
    }
    }
    Java - Singleton

    View full-size slide

  93. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  94. import org.junit.jupiter.api.Test;
    import static org.assertj.core.api.Assertions.assertThat;
    class MySingletonTest {
    @Test
    public void somethingIsDoneWithAbcIsSetAsASystemProperty(){
    System.setProperty("com.example", "abc");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("abc");
    }
    @Test
    public void somethingElseIsDoneWithXyzIsSetAsASystemProperty(){
    System.setProperty("com.example", "xyz");
    MySingleton singleton = MySingleton.getInstance();
    assertThat(singleton.getSomething()).isEqualTo("xyz");
    }
    }
    Java - Singleton

    View full-size slide

  95. The Liar 4
    The Giant 5
    The Mockery 1
    The Inspector 7
    Generous Leftovers 5
    The Local Hero 7
    The Nitpicker 8
    The Secret Catcher 7
    The Dodger 8
    The Loudmouth 8
    Anti patterns
    The Greedy Catcher 7
    Excessive Setup 3
    The Sequencer 7
    Hidden Dependency 2
    The Enumerator 8
    The Stranger 7
    The Operating System Evangelist 8
    Success Against All Odds 5
    The Free Ride 8
    The One 7
    The Peeping Tom 7
    The Slow Poke 6

    View full-size slide

  96. The Liar 4
    The Giant 5
    The Mockery 1
    The Inspector 7
    Generous Leftovers 5
    The Local Hero 7
    The Nitpicker 8
    The Secret Catcher 7
    The Dodger 8
    The Loudmouth 8
    Anti patterns
    The Greedy Catcher 7
    Excessive Setup 3
    The Sequencer 7
    Hidden Dependency 2
    The Enumerator 8
    The Stranger 7
    The Operating System Evangelist 8
    Success Against All Odds 5
    The Free Ride 8
    The One 7
    The Peeping Tom 7
    The Slow Poke 6

    View full-size slide

  97. ● The One
    ● The Peeping Tom
    What we covered

    View full-size slide

  98. ● The One
    ○ Anti patterns can be mixed between each other
    ○ In open source projects it is usually a mix
    ● The Peeping Tom
    What we covered

    View full-size slide

  99. ● The One
    ○ Anti patterns can be mixed between each other
    ○ In open source projects it is usually a mix
    ● The Peeping Tom
    ○ Once again, avoid global state
    What we covered

    View full-size slide

  100. 4. The flash ⚡
    Crafting code

    View full-size slide

  101. 4. The flash ⚡
    Developers that gets blocked trying to practice TDD, and
    before splitting up the test in smaller chunks, they are
    thinking about all the edge cases that the test would cover.
    This can lead to another anti patterns itself.
    Crafting code

    View full-size slide

  102. Test methods should be easy to read, pretty much straight line code. If
    a test method is getting long and complicated, then you need to play
    "Baby Steps."
    Kent Beck - TDD by example

    View full-size slide

  103. Focuses on generalization
    or performance issues from the start
    The flash

    View full-size slide

  104. Aggregates
    It potentially leads to a combination of
    different anti-patterns, like The One
    The flash

    View full-size slide

  105. 5. The jumper
    Crafting code

    View full-size slide

  106. 5. The jumper
    The practice of trying to follow the test driven development
    approach, but jumping up to the next steps of the flow
    before completing the one before.
    Crafting code

    View full-size slide

  107. Tdd loop here (and potentially share the
    xp meetup)

    View full-size slide

  108. Tdd loop here (and potentially share the
    xp meetup)
    Trying to make it "perfect" from the start

    View full-size slide

  109. Tdd loop here (and potentially share the
    xp meetup)
    Trying to make it "perfect" from the start Get blocked by not knowing what to code

    View full-size slide

  110. Tdd loop here (and potentially share the
    xp meetup)
    - Refactor on the red
    - Changing class name
    - Fixing styles (any kind of style)
    - Changing files that are not related to
    the test
    Trying to make it "perfect" from the start Get blocked by not knowing what to code

    View full-size slide

  111. Tdd loop here (and potentially share the
    xp meetup)
    - Refactor on the red
    - Changing class name
    - Fixing styles (any kind of style)
    - Changing files that are not related to
    the test
    Trying to make it "perfect" from the start Get blocked by not knowing what to code

    View full-size slide

  112. Tdd loop here (and potentially share the
    xp meetup) Not trusting the hard coded ("I know it
    will pass")

    View full-size slide

  113. Tdd loop here (and potentially share the
    xp meetup)
    Making changes that break the tests

    View full-size slide

  114. 6. Wrapping up
    We are almost done!
    Crafting code

    View full-size slide

  115. ● The One
    ● The Peeping Tom
    ● The flash
    ● The jumper
    What we covered

    View full-size slide

  116. https://www.codurance.com/publications/building-testing-culture
    https://www.codurance.com/publications/tdd-anti-patterns-chapter-1

    View full-size slide

  117. https://www.codurance.com/publications/building-testing-culture
    https://www.codurance.com/publications/building-testing-culture

    View full-size slide

  118. https://www.codurance.com/events

    View full-size slide

  119. Matheus Marabesi
    Hello there, you can call me Marabesi,
    But my name is Matheus Marabesi, I work at Codurance as a
    Software craftsperson.
    I enjoy talking about anything related to: testing, patterns and
    gamification.
    You can find me at @MatheusMarabesi or https://marabesi.com
    Codurance
    Crafting Code

    View full-size slide