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

TDD anti-patterns at Codurance Spain

Marabesi
October 14, 2021

TDD anti-patterns at Codurance Spain

Video available at https://app.livestorm.co/codurance/testing-anti-patterns-workshop

Testing practices have increased 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 TDD anti-patterns, a list inspired by James Carr. From his list, those are the ones I consider the most popular anti-patterns: The liar, Excessive setup, The Slow Poke.

Besides that, we are going to dive into what they are and how to avoid them to keep your test suite sharp.

In this session the focus will be on the theory part of TDD and the anti-patterns to avoid. This talk assumes that the audience already has some knowledge on TDD and wants to improve their craft. The format will use code snippets to explore each anti-pattern.

https://www.meetup.com/pt-BR/codurance-craft-events/events/280794032

https://marabesi.com/tdd/2021/08/28/tdd-anti-patterns.html

Marabesi

October 14, 2021
Tweet

More Decks by Marabesi

Other Decks in Programming

Transcript

  1. 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
  2. 1. Intro - Background 2. Excessive setup 3. The Liar

    4. The giant 5. The slow poke 6. Wrapping up Crafting code Agenda
  3. TDD

  4. 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
  5. The Liar 4 The Giant 5 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 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
  6. 2. Excessive setup - 🏆3 A test that requires a

    lot of work setting up in order to even begin testing. Sometimes several hundred lines of code is used to setup the environment for one test, with several objects involved, which can make it difficult to really ascertain what is tested due to the “noise” of all of the setup going on. Crafting code
  7. describe('server: server', () => { beforeAll(() => { jest.spyOn(path, 'join').mockImplementation((...args)

    => `join(${args.join(', ')})`) jest.spyOn(path, 'resolve').mockImplementation((...args) => `resolve(${args.join(', ')})`) connect.mockReturnValue({ use: jest.fn() }) serveStatic.mockImplementation(dir => ({ id: 'test-serve-static', dir })) nuxtMiddleware.mockImplementation(options => ({ id: 'test-nuxt-middleware', ...options })) errorMiddleware.mockImplementation(options => ({ id: 'test-error-middleware', ...options })) createTimingMiddleware.mockImplementation(options => ({ id: 'test-timing-middleware', ...options })) // piece of code hidden }) Jest - javascript Jest - javascript - Nuxtjs
  8. describe('server: server', () => { beforeAll(() => { jest.spyOn(path, 'join').mockImplementation((...args)

    => `join(${args.join(', ')})`) jest.spyOn(path, 'resolve').mockImplementation((...args) => `resolve(${args.join(', ')})`) connect.mockReturnValue({ use: jest.fn() }) serveStatic.mockImplementation(dir => ({ id: 'test-serve-static', dir })) nuxtMiddleware.mockImplementation(options => ({ id: 'test-nuxt-middleware', ...options })) errorMiddleware.mockImplementation(options => ({ id: 'test-error-middleware', ...options })) createTimingMiddleware.mockImplementation(options => ({ id: 'test-timing-middleware', ...options })) // piece of code hidden }) Jest - javascript Jest - javascript - Nuxtjs
  9. describe('server: server', () => { beforeAll(() => { jest.spyOn(path, 'join').mockImplementation((...args)

    => `join(${args.join(', ')})`) jest.spyOn(path, 'resolve').mockImplementation((...args) => `resolve(${args.join(', ')})`) connect.mockReturnValue({ use: jest.fn() }) serveStatic.mockImplementation(dir => ({ id: 'test-serve-static', dir })) nuxtMiddleware.mockImplementation(options => ({ id: 'test-nuxt-middleware', ...options })) errorMiddleware.mockImplementation(options => ({ id: 'test-error-middleware', ...options })) createTimingMiddleware.mockImplementation(options => ({ id: 'test-timing-middleware', ...options })) // piece of code hidden }) Jest - javascript Jest - javascript - Nuxtjs
  10. test('should construct server', () => { const nuxt = createNuxt()

    // piece of code hidden let server = new Server(nuxt) expect(server.nuxt.hook).toBeCalledWith('close', expect.any(Function)) // piece of code hidden const closeHook = server.nuxt.hook.mock.calls[0][1] server.close = jest.fn() expect(server.close).not.toBeCalled() closeHook() expect(server.close).toBeCalledTimes(1) // piece of code hidden server = new Server(nuxt) expect(server.publicPath).toBe(nuxt.options.build._publicPath) }) Jest - javascript - Nuxtjs
  11. test('should construct server', () => { const nuxt = createNuxt()

    // piece of code hidden let server = new Server(nuxt) expect(server.nuxt.hook).toBeCalledWith('close', expect.any(Function)) // piece of code hidden const closeHook = server.nuxt.hook.mock.calls[0][1] server.close = jest.fn() expect(server.close).not.toBeCalled() closeHook() expect(server.close).toBeCalledTimes(1) // piece of code hidden server = new Server(nuxt) expect(server.publicPath).toBe(nuxt.options.build._publicPath) }) Jest - javascript - Nuxtjs
  12. const Wrapped = ( code, test, testCaseTests, sourceCodeTests, guideContent, whenDoneRedirectTo,

    waitCodeToBeExecutedOnStep, enableEditorOnStep, trackSection, testCaseStrategy, sourceCodeStrategy, disableEditor, introContent, enableIntroOnStep, editorOptions, attentionAnimationTo = [] ) => { } Jest - Javascript - Reactjs
  13. const Wrapped = ( code, test, testCaseTests, sourceCodeTests, guideContent, whenDoneRedirectTo,

    waitCodeToBeExecutedOnStep, enableEditorOnStep, trackSection, testCaseStrategy, sourceCodeStrategy, disableEditor, introContent, enableIntroOnStep, editorOptions, attentionAnimationTo = [] ) => { } Jest - Javascript - Reactjs
  14. test('should accept editor options by parameter', () => { const

    HoC = Rocket( null, null, null, null, null, null, null, 'my-section', null, null, null, null, { [SOURCE_CODE]: { readOnly: true }, [TEST_CODE]: {} } ); const wrapper = shallow(<HoC />); expect(wrapper.instance().state.editorOptions[SOURCE_CODE].readOnly).toBe(true); expect(wrapper.find('EditorManager').props().options[SOURCE_CODE].readOnly).toEqual(true); }); Jest - Javascript - Reactjs
  15. test('should accept editor options by parameter', () => { const

    HoC = Rocket( null, null, null, null, null, null, null, 'my-section', null, null, null, null, { [SOURCE_CODE]: { readOnly: true }, [TEST_CODE]: {} } ); const wrapper = shallow(<HoC />); expect(wrapper.instance().state.editorOptions[SOURCE_CODE].readOnly).toBe(true); expect(wrapper.find('EditorManager').props().options[SOURCE_CODE].readOnly).toEqual(true); }); Jest - Javascript - Reactjs
  16. test('should accept editor options by parameter', () => { const

    HoC = Rocket( null, null, null, null, null, null, null, 'my-section', null, null, null, null, { [SOURCE_CODE]: { readOnly: true }, [TEST_CODE]: {} } ); const wrapper = shallow(<HoC />); expect(wrapper.instance().state.editorOptions[SOURCE_CODE].readOnly).toBe(true); expect(wrapper.find('EditorManager').props().options[SOURCE_CODE].readOnly).toEqual(true); }); Jest - Javascript - Reactjs
  17. test('should accept editor options by parameter', () => { const

    HoC = Rocket( null, null, null, null, null, null, null, 'my-section', null, null, null, null, { [SOURCE_CODE]: { readOnly: true }, [TEST_CODE]: {} } ); const wrapper = shallow(<HoC />); expect(wrapper.instance().state.editorOptions[SOURCE_CODE].readOnly).toBe(true); expect(wrapper.find('EditorManager').props().options[SOURCE_CODE].readOnly).toEqual(true); }); Jest - Javascript - Reactjs
  18. /** * Makes sure the use of "localhost" in the

    Hudson URL reports a warning. */ @Test public void localhostWarning() throws Exception { HtmlPage p = j.createWebClient().goTo("configure"); HtmlInput url = p.getFormByName("config").getInputByName("_.url"); url.setValueAttribute("http://localhost:1234/"); assertThat( p.getDocumentElement().getTextContent(), containsString("instead of localhost") ); } Junit - Java - Jenkins
  19. /** * Makes sure the use of "localhost" in the

    Hudson URL reports a warning. */ @Test public void localhostWarning() throws Exception { HtmlPage p = j.createWebClient().goTo("configure"); HtmlInput url = p.getFormByName("config").getInputByName("_.url"); url.setValueAttribute("http://localhost:1234/"); assertThat( p.getDocumentElement().getTextContent(), containsString("instead of localhost") ); } Junit - Java Junit - Java - Jenkins
  20. /** * Makes sure the use of "localhost" in the

    Hudson URL reports a warning. */ @Test public void localhostWarning() throws Exception { HtmlPage p = j.createWebClient().goTo("configure"); HtmlInput url = p.getFormByName("config").getInputByName("_.url"); url.setValueAttribute("http://localhost:1234/"); assertThat( p.getDocumentElement().getTextContent(), containsString("instead of localhost") ); } Junit - Java Junit - Java - Jenkins
  21. /** * Makes sure the use of "localhost" in the

    Hudson URL reports a warning. */ @Test public void localhostWarning() throws Exception { HtmlPage p = j.createWebClient().goTo("configure"); HtmlInput url = p.getFormByName("config").getInputByName("_.url"); url.setValueAttribute("http://localhost:1234/"); assertThat( p.getDocumentElement().getTextContent(), containsString("instead of localhost") ); } Junit - Java Junit - Java - Jenkins
  22. /** * Makes sure the use of "localhost" in the

    Hudson URL reports a warning. */ @Test public void localhostWarning() throws Exception { HtmlPage p = j.createWebClient().goTo("configure"); HtmlInput url = p.getFormByName("config").getInputByName("_.url"); url.setValueAttribute("http://localhost:1234/"); assertThat( p.getDocumentElement().getTextContent(), containsString("instead of localhost") ); } Junit - Java Junit - Java - Jenkins
  23. /** * Makes sure the use of "localhost" in the

    Hudson URL reports a warning. */ @Test public void localhostWarning() throws Exception { HtmlPage p = j.createWebClient().goTo("configure"); HtmlInput url = p.getFormByName("config").getInputByName("_.url"); url.setValueAttribute("http://localhost:1234/"); assertThat( p.getDocumentElement().getTextContent(), containsString("instead of localhost") ); } Junit - Java Junit - Java - Jenkins
  24. • Adding tests after the source code • Lack of

    SOLID principles • Object Calisthenics? Root cause
  25. 3. The liar - 🏆4 An entire unit test that

    passes all of the test cases it has and appears valid, but upon closer inspection it is discovered that it doesn’t really test the intended target at all. Crafting code
  26. test('the data is peanut butter', () => { function callback(data)

    { expect(data).toBe('peanut butter'); } fetchData(callback); }); Jest - javascript
  27. test('the data is peanut butter', () => { function callback(data)

    { expect(data).toBe('peanut butter'); } fetchData(callback); }); Jest - javascript
  28. test('the data is peanut butter', () => { function callback(data)

    { expect(data).toBe('peanut butter'); } fetchData(callback); }); Jest - javascript
  29. test('the data is peanut butter', done => { function callback(data)

    { try { expect(data).toBe('peanut butter'); done(); } catch (error) { done(error); } } fetchData(callback); }); Jest - javascript
  30. test('the data is peanut butter', done => { function callback(data)

    { try { expect(data).toBe('peanut butter'); done(); } catch (error) { done(error); } } fetchData(callback); }); Jest - javascript
  31. test('the data is peanut butter', done => { function callback(data)

    { try { expect(data).toBe('peanut butter'); done(); } catch (error) { done(error); } } fetchData(callback); }); Jest - javascript
  32. test('the data is peanut butter', done => { function callback(data)

    { try { expect(data).toBe('peanut butter'); done(); } catch (error) { done(error); } } fetchData(callback); }); Jest - javascript
  33. test('the data is peanut butter', done => { function callback(data)

    { try { expect(data).toBe('peanut butter'); done(); } catch (error) { done(error); } } fetchData(callback); }); Jest - javascript
  34. @Test fun `update user`() { val userId = 999 service.updateUserCustomAttributes(

    userId, mapOf(UserCustomAttribute.JOB to "MANAGER") ) } @Test fun `delete user`() { val userId = UserId.fromUuidString("e080-c8a-41bb-8ef-415124637e99") service.deleteUser(userId) } Junit - kotlin
  35. @Test fun `update user`() { val userId = 999 service.updateUserCustomAttributes(

    userId, mapOf(UserCustomAttribute.JOB to "MANAGER") ) } @Test fun `delete user`() { val userId = UserId.fromUuidString("e080-c8a-41bb-8ef-415124637e99") service.deleteUser(userId) } Junit - kotlin
  36. @Test fun `update user`() { val userId = 999 service.updateUserCustomAttributes(

    userId, mapOf(UserCustomAttribute.JOB to "MANAGER") ) } @Test fun `delete user`() { val userId = UserId.fromUuidString("e080-c8a-41bb-8ef-415124637e99") service.deleteUser(userId) } Junit - kotlin
  37. 4. The giant - 🏆5 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. 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
  43. $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
  44. $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
  45. $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
  46. $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
  47. $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
  48. $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
  49. $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
  50. $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
  51. $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
  52. $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
  53. $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
  54. $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
  55. $result = Converter::degreeToAngle($value); $this->assertEquals((int) round($value * 60000), $result); $result =

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

    Converter::angleToDegree($value); $this->assertEquals(round($value / 60000), $result); } } PHPUnit - PHPOffice/Word
  57. • How many test cases do I have? • Lacks

    feedback from the test • Data provider / Parameterized tests Points of attention
  58. 5. The slow poke - 🏆6 A unit test that

    runs incredibly slow. When developers kick it off, they have time to go to the bathroom, grab a smoke, or worse, kick the test off before they go home at the end of the day. Crafting code
  59. test('should show Buggy on user interaction by keyboard', done =>

    { const wrapper = mount( <Guide guideContent={content} currentHint={0} showNext={false} invalidCode={false} afkExpirationTime={400} /> ); setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown', {keyCode: 37}); document.dispatchEvent(keypress); Jest - Javascript - Reactjs
  60. test('should show Buggy on user interaction by keyboard', done =>

    { const wrapper = mount( <Guide guideContent={content} currentHint={0} showNext={false} invalidCode={false} afkExpirationTime={400} /> ); setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown', {keyCode: 37}); document.dispatchEvent(keypress); Jest - Javascript - Reactjs
  61. setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown',

    {keyCode: 37}); document.dispatchEvent(keypress); wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(0); done(); }, 500); }); Jest - Javascript - Reactjs
  62. setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown',

    {keyCode: 37}); document.dispatchEvent(keypress); wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(0); done(); }, 500); }); Jest - Javascript - Reactjs
  63. setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown',

    {keyCode: 37}); document.dispatchEvent(keypress); wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(0); done(); }, 500); }); Jest - Javascript - Reactjs
  64. setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown',

    {keyCode: 37}); document.dispatchEvent(keypress); wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(0); done(); }, 500); }); Jest - Javascript - Reactjs
  65. setTimeout(() => { wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(1); const keypress = new KeyboardEvent('keydown',

    {keyCode: 37}); document.dispatchEvent(keypress); wrapper.update(); expect(wrapper.find('BuggySleepy').length).toBe(0); done(); }, 500); }); Jest - Javascript - Reactjs
  66. • CRON jobs • Leap year / any time related

    • Lack of control over non-determinism Points of attention
  67. Focus more on integration test instead of unit, this can

    lead to slow suites. This also can happen when focusing too much on coverage instead of having it as a side effect. Points of attention
  68. Trying to reverse engineer the TDD flow. It often happens

    when there is no tests on the code and as soon as developers start to add them, it goes back to integration test and coverage. Points of attention
  69. Ice cream cone Testing is Good. Pyramids are Bad. Ice

    Cream Cones are the Worst - Stephen H Fishman
  70. Crafting code Testing is Good. Pyramids are Bad. Ice Cream

    Cones are the Worst - Stephen H Fishman
  71. • The liar • Excessive setup • The giant •

    The slow poke • and many more! What we covered
  72. 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