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

TDD anti patterns - episode 3 - With Juan Pablo

Marabesi
February 10, 2022

TDD anti patterns - episode 3 - With Juan Pablo

Testing practices has increasing its adoption by developers, shifting left the test responsibilities
And increasing the quality of the code, besides that, continuous testing is an agile practice that impacts the software development life cycle.

In this talk we are going to focus on the following TDD anti-patterns: The nitpicker, The secret catcher, The dodger and The Loudmouth. This is the third out of 6 in the testing anti-patterns series.

Marabesi

February 10, 2022
Tweet

More Decks by Marabesi

Other Decks in Programming

Transcript

  1. TDD - EP 3
    codurance.com
    Testing anti-patterns - The nitpicker,
    The secret catcher, The dodger, The
    Loudmouth

    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 nitpicker
    3. The secret catcher
    4. The dodger
    5. The Loudmouth
    6. Wrapping up
    Crafting code
    Agenda

    View full-size slide

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

    View full-size slide

  5. 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

  6. The Liar 4
    The Giant 5
    The Mockery 1
    The Inspector 7
    Generous Leftovers 5
    The Local Hero 7
    The Nitpicker
    The Secret Catcher
    The Dodger
    The Loudmouth
    Anti patterns
    The Greedy Catcher
    Excessive Setup 3
    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 6

    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
    The Secret Catcher
    The Dodger
    The Loudmouth
    Anti patterns
    The Greedy Catcher
    Excessive Setup 3
    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 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. Survey notes: Companies argue that TDD requires more time to complete a task and the team
    don't have time for it

    View full-size slide

  9. 2. Anti-patterns - Episode 3
    The nitpicker, The secret catcher, The
    dodger and The Loudmounth
    Getting started

    View full-size slide

  10. 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

  11. The Liar
    The Giant
    The Mockery
    The Inspector
    Generous Leftovers
    The Local Hero
    The Nitpicker8
    The Secret Catcher7
    The Dodger8
    The Loudmouth8
    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

  12. Survey
    54.6%
    Agree

    View full-size slide

  13. Survey
    45.4%
    Neutral + disagree

    View full-size slide

  14. 2. The nitpicker - 🏆8
    A unit test which compares a complete output
    when it’s really only interested in small parts of
    it, so the test has to continually be kept in line
    with otherwise unimportant details. Endemic in
    web application testing.
    Crafting code

    View full-size slide

  15. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  16. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  17. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  18. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  19. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  20. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  21. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertExactJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  22. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  23. public function testDeleteApplication()
    {
    $response = $this->postApplication();
    $this->assertFalse($response->error);
    $this->delete('api/application/' . $response->data)
    ->assertJson([
    'data' => (string) $response->data,
    'error' => false
    ]);
    }
    PHP - Laravel

    View full-size slide

  24. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  25. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  26. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  27. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  28. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  29. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  30. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  31. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  32. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  33. describe('#getSignedCookies()', function() {
    it('should create cookies object', function(done) {
    var result = CloudfrontUtil.getSignedCookies(
    'http://foo.com', defaultParams);
    expect(result).to.have.property('CloudFront-Policy');
    expect(result).to.have.property('CloudFront-Signature');
    expect(result).to.have.property('CloudFront-Key-Pair-Id');
    done();
    });
    });
    Javascript - chai

    View full-size slide

  34. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  35. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  36. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  37. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  38. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  39. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  40. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  41. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  42. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  43. @Test
    fun `should calculate CFR correctly by monthly and the time split works well ( cross a calendar month)`() {
    val requestBody = """ { skipped code } """.trimIndent()
    RestAssured
    .given()
    .contentType(ContentType.JSON)
    .body(requestBody)
    .post("/api/pipeline/metrics")
    .then()
    .statusCode(200)
    .body("changeFailureRate.summary.value", equalTo(30.0F))
    .body("changeFailureRate.summary.level", equalTo("MEDIUM"))
    .body("changeFailureRate.details[0].value", equalTo("NaN"))
    .body("changeFailureRate.details[1].value", equalTo("NaN"))
    .body("changeFailureRate.details[2].value", equalTo(30.0F))
    }
    Kotlin - RestAssured

    View full-size slide

  44. ● Use what you need
    ● It can be generalized to other applications (CLI for example)
    Points of attention

    View full-size slide

  45. 3. The Secret Catcher - 🏆7
    A test that at first glance appears to be doing no
    testing due to the absence of assertions, but as
    they say, “the devil’s in the details.” The test is
    really relying on an exception to be thrown when
    a mishap occurs, and is expecting the testing
    framework to capture the exception and report it
    to the user as a failure.
    Crafting code

    View full-size slide

  46. Reflection - Java

    View full-size slide

  47. Reflection - Java

    View full-size slide

  48. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText(Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript

    View full-size slide

  49. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript

    View full-size slide

  50. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript

    View full-size slide

  51. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript

    View full-size slide

  52. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript

    View full-size slide

  53. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript

    View full-size slide

  54. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    });
    Jest - Javascript
    👀

    View full-size slide

  55. test('it handles error when removing credit card ', async () => {
    const data = await Payment.asyncData(asyncDataContext);
    data.paymentMethod = PaymentMethod.CREDIT_CARD;
    const { getAllByText } = render(Payment, {
    mocks,
    data() {
    return { ...data };
    },
    });
    const [removeButton] = getAllByText('Remove');
    await fireEvent.click(removeButton);
    expect(getByText('Some error')).toBeInTheDocument();
    });
    Jest - Javascript

    View full-size slide

  56. Reflection - Java

    View full-size slide

  57. Software engineering unlocked, Dr. McKayla
    Because well, if, if you know, a smoke test could also execute a lot of
    the code base. Actually just, you know, make sure that the code run
    somehow without verifying that, you know, the inputs and outputs are
    matching and so on.
    Dr. Mauricio’s Aniche

    View full-size slide

  58. ● Context matters
    Points of attention

    View full-size slide

  59. ● Lack of practice on TDD
    ● Oriented to coverage
    Root cause

    View full-size slide

  60. 4. The Dodger - 🏆8
    A unit test which has lots of tests for minor
    (and presumably easy to test) side effects, but
    never tests the core desired behavior.
    Sometimes you may find this in database
    access related tests, where a method is called,
    then the test selects from the database and
    runs assertions against the result.
    Crafting code

    View full-size slide

  61. http://blog.cleancoder.com/uncle-bob/2017/10/03/TestContravariance.html

    View full-size slide

  62. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  63. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  64. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  65. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  66. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  67. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  68. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  69. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  70. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  71. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  72. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  73. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  74. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  75. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  76. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  77. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  78. /**
    * Tests that objects works as expected.
    */
    public function testObject(): void {
    $author = Author::createFromArray($this->getSampleId(), $this->getSampleValues());
    $this->assertEquals($this->getSampleId(), $author->getId());
    $this->assertEquals($this->getSampleValues()['name']['given'], $author->getNameGiven());
    $this->assertEquals($this->getSampleValues()['name']['family'], $author->getNameFamily());
    $this->assertEquals($this->getSampleValues()['country'], $author->getCountry());
    $this->assertEquals($this->getSampleValues()['org']['name'], $author->getOrgName());
    $this->assertEquals($this->getSampleValues()['org']['unit'], $author->getOrgUnit());
    $this->assertEquals($this->getSampleValues()['homepage'], $author->getHomepage());
    $this->assertEquals($this->getSampleValues()['description'], $author->getDescription());
    $this->assertEquals($this->getSampleValues()['image'], $author->getImage());
    $this->assertEquals($this->getSampleValues()['identification'], $author->getIdentification());
    $this->assertEquals($this->getSampleValues()['identification']['email'],
    $author->getIdentification('email'));
    $this->assertEquals([], $author->getIdentification('not exist'));
    $this->assertEquals($author->checksum(), $author->checksum());
    }
    Drupal - PHP

    View full-size slide

  79. ● 1-1 one test class to one production class
    ● Focus on implementation details rather than behavior
    Points of attention

    View full-size slide

  80. 5. The Loudmouth - 🏆8
    A unit test (or test suite) that clutters up the
    console with diagnostic messages, logging
    messages, and other miscellaneous chatter,
    even when tests are passing.
    Crafting code

    View full-size slide

  81. test.each([['function']])(
    'should not bubble up the error when a invalid source code
    is provided',
    (code) => {
    const strategy = jest.fn();
    const result = Reason(code, strategy);
    expect(strategy).toHaveBeenCalledTimes(0);
    expect(result).toBeFalsy();
    }
    );
    Console log - Javascript

    View full-size slide

  82. test.each([['function']])(
    'should not bubble up the error when a invalid source code
    is provided',
    (code) => {
    const strategy = jest.fn();
    const result = Reason(code, strategy);
    expect(strategy).toHaveBeenCalledTimes(0);
    expect(result).toBeFalsy();
    }
    );
    Console log - Javascript

    View full-size slide

  83. test.each([['function']])(
    'should not bubble up the error when a invalid source code
    is provided',
    (code) => {
    const strategy = jest.fn();
    const result = Reason(code, strategy);
    expect(strategy).toHaveBeenCalledTimes(0);
    expect(result).toBeFalsy();
    }
    );
    Console log - Javascript

    View full-size slide

  84. test.each([['function']])(
    'should not bubble up the error when a invalid source code
    is provided',
    (code) => {
    const strategy = jest.fn();
    const result = Reason(code, strategy);
    expect(strategy).toHaveBeenCalledTimes(0);
    expect(result).toBeFalsy();
    }
    );
    Console log - Javascript

    View full-size slide

  85. const reason = function(code, strategy) {
    try {
    const ast = esprima.parseScript(code);
    if (ast.body.length > 0) {
    return strategy(ast);
    }
    } catch (error) {
    /* eslint-disable-next-line */
    console.warn(error);
    return false;
    }
    };
    Console log - Javascript

    View full-size slide

  86. const reason = function(code, strategy) {
    try {
    const ast = esprima.parseScript(code);
    if (ast.body.length > 0) {
    return strategy(ast);
    }
    } catch (error) {
    /* eslint-disable-next-line */
    console.warn(error);
    return false;
    }
    };
    Console log - Javascript

    View full-size slide

  87. const reason = function(code, strategy) {
    try {
    const ast = esprima.parseScript(code);
    if (ast.body.length > 0) {
    return strategy(ast);
    }
    } catch (error) {
    /* eslint-disable-next-line */
    console.warn(error);
    return false;
    }
    };
    Console log - Javascript

    View full-size slide

  88. const reason = function(code, strategy) {
    try {
    const ast = esprima.parseScript(code);
    if (ast.body.length > 0) {
    return strategy(ast);
    }
    } catch (error) {
    /* eslint-disable-next-line */
    console.warn(error);
    return false;
    }
    };
    Console log - Javascript

    View full-size slide

  89. const originalConsole = globalThis.console;
    beforeEach(() => {
    globalThis.console = {
    warn: jest.fn(),
    error: jest.fn(),
    log: jest.fn()
    };
    });
    afterEach(() => {
    globalThis.console = originalConsole;
    });
    Console log - Javascript

    View full-size slide

  90. const originalConsole = globalThis.console;
    beforeEach(() => {
    globalThis.console = {
    warn: jest.fn(),
    error: jest.fn(),
    log: jest.fn()
    };
    });
    afterEach(() => {
    globalThis.console = originalConsole;
    });
    Console log - Javascript

    View full-size slide

  91. const originalConsole = globalThis.console;
    beforeEach(() => {
    globalThis.console = {
    warn: jest.fn(),
    error: jest.fn(),
    log: jest.fn()
    };
    });
    afterEach(() => {
    globalThis.console = originalConsole;
    });
    Console log - Javascript

    View full-size slide

  92. const originalConsole = globalThis.console;
    beforeEach(() => {
    globalThis.console = {
    warn: jest.fn(),
    error: jest.fn(),
    log: jest.fn()
    };
    });
    afterEach(() => {
    globalThis.console = originalConsole;
    });
    Console log - Javascript

    View full-size slide

  93. ● Clean up if not needed
    ● Threat the logs as a feature, test drive them
    Points of attention

    View full-size slide

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

    View full-size slide

  95. ● The nitpicker
    ● The secret catcher
    ● The dodger
    ● The Loudmounth
    ● and many more!
    What we covered

    View full-size slide

  96. https://www.codurance.com/publications/tdd-anti-patterns-chapter-1
    https://www.codurance.com/publications/tdd-anti-patterns-chapter-2

    View full-size slide

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

    View full-size slide

  98. 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