List

Your TDD Treasure Map

Your TDD Treasure Map

by Christopher "Aji" Slater

In his presentation "Your TDD Treasure Map" at RailsConf 2022, Christopher "Aji" Slater focuses on the importance of test-driven development (TDD) and offers strategies for applying it effectively. Slater begins by acknowledging that while testing is crucial in software development, many developers, especially those new to the field, struggle to implement it. Using the metaphor of a treasure map, he illustrates how flowcharts can help navigate the complexities of testing and writing code.

Key Points Discussed:

  • Significance of Testing: Slater emphasizes that robust automated tests can prevent regressions, support refactoring, provide documentation, and guide design decisions.
  • Treasure Map Analogy: He introduces the idea of a treasure map as a visual representation of code flow, explaining that it can serve as a guide for developers to identify decision points in their code, which can lead to different outcomes, much like a flowchart leading to treasure or peril.
  • Flowcharts in Testing: Slater demonstrates how to create a flowchart based on acceptance criteria and then use it to generate test cases, reflecting the control flow in the application. He presents a practical example of a Rails controller handling user updates, showcasing how to derive test cases from the map.
  • Contextual Testing: The discussion includes how to handle different contexts within the testing framework and how variations in parameters or decision branches can affect the flow of execution.
  • Incremental Development: Slater highlights the iterative nature of TDD, encouraging developers to begin with simple tests and gradually add complexity based on user stories and acceptance criteria.
  • Encapsulation of Logic: He advises on encapsulating complex logic in service objects, discussing how this can simplify the flowchart and testing by abstracting responsibilities away from controllers.
  • Final Thoughts: The presentation illustrates that there are no strict rules for applying the treasure map technique; instead, it is a flexible approach that can be adapted to various development frameworks.

Main Takeaways:

  • TDD is a valuable approach for ensuring software integrity and can be made approachable through visual mapping techniques.
  • Using flowcharts to visualize decision paths enables developers to better understand how to structure tests for their code.
  • The process of writing tests should be seen as non-linear; it evolves through iterative exploration and adjustment of the codebase.
  • Practical application examples are crucial to grounding testing strategies in real-world development scenarios.

Through this engaging talk, Slater equips both novice and seasoned developers with insights and techniques for navigating the sometimes treacherous waters of TDD, ultimately steering them towards a more robust test suite.

We know testing is vital and makes refactoring painless. But how to set sail to that TDD treasure? Yarr, we need to test to get experience, but need experience to test. Let’s draw a map with simple strategies for identifying test cases and building a robust test suite. X marks the spot w/ TDD tools for newbies and seasoned pirates alike.

RailsConf 2022

00:00:00.900 foreign
00:00:12.599 hello hello welcome everybody thank you
00:00:14.820 so much for coming out I mean Ahoy
00:00:21.660 shouting into the microphone that's
00:00:22.980 always great my name is Aji that's a
00:00:25.680 hard J uh I've been a professional
00:00:28.019 developer since 2016 but if you count
00:00:30.720 geocities I've been putting code on the
00:00:32.880 web since 1996.
00:00:36.000 uh anyone in the room not yet born in
00:00:38.460 1996 hence
00:00:41.040 a couple of you that's awesome I'm so
00:00:43.079 glad you're here I am regretting that I
00:00:45.480 asked that question a little bit though
00:00:49.020 so I do uh never really know what to say
00:00:51.480 during these intros so
00:00:53.940 um how about in fourth grade I got the
00:00:56.579 lead in the school play of mice and
00:00:58.920 Mozart where we told the life story of
00:01:01.079 Wolfgang Amadeus Mozart Through The Eyes
00:01:03.239 of a family of mice that lived in his
00:01:05.040 walls I played Mozart at nine and I've
00:01:07.680 been trying to relive That Glory ever
00:01:09.299 since
00:01:11.400 so I'm going to take a guess that we're
00:01:13.439 on the same page about something
00:01:15.720 I'm going to assume that everyone here
00:01:18.000 agrees that testing is important
00:01:21.540 and that test driven development can be
00:01:23.580 massively beneficial
00:01:25.560 you're here at a software Conference of
00:01:28.619 a community that overwhelmingly
00:01:30.240 appreciates automated testing and you
00:01:32.700 came to listen to your tdd treasure map
00:01:34.799 which might just imply that tdd is a
00:01:37.560 kind of treasure
00:01:39.540 so I'm going to skip the arguments that
00:01:41.280 try and convince you of the benefits of
00:01:43.140 robust automated tests that verify your
00:01:46.020 code is working properly defend against
00:01:48.479 regressions support refactoring act as
00:01:51.840 living documentation and provide design
00:01:53.939 guidance
00:01:55.799 and all although I didn't really
00:01:57.180 understand the Nuance at the time that
00:01:59.700 was certainly the feeling they tried to
00:02:01.320 instill in us at my coding boot camp
00:02:04.079 but we had so little time I graduated
00:02:06.840 however having never written a test
00:02:08.759 without feeling the benefits of a good
00:02:11.160 test Suite plus it seemed like a paradox
00:02:14.599 right right the thing that verifies the
00:02:17.459 code that I will have written before I
00:02:19.860 am going to have written the code that I
00:02:21.540 will have been about to write
00:02:23.580 yeah sure let me just jump into my time
00:02:25.500 machine and take a look at that PR I'm
00:02:27.120 going to put up tomorrow
00:02:29.459 testing first can be difficult
00:02:31.920 that's true for seasoned Sailors but
00:02:34.080 even more so for those newer to this
00:02:35.940 career when it's a challenge to even
00:02:37.920 reason about what code to write at all
00:02:41.099 how was I going to make it out of this
00:02:42.660 mess
00:02:43.860 like Archimedes in the bathtub or Newton
00:02:46.379 and gravity we need a compelling yet
00:02:48.420 apocryphal story of Discovery to go with
00:02:50.459 it
00:02:51.660 so scratching my head over this problem
00:02:53.640 I wandered over to my bookshelf that has
00:02:55.560 all of my Joby job career type books
00:02:58.319 there's Sandy Metz practical
00:02:59.959 object-oriented design in Ruby there's
00:03:03.000 Atul gawandes the checklist Manifesto
00:03:05.540 wonderful tomes that have set me on the
00:03:07.920 path when I've needed them before
00:03:10.800 wait
00:03:12.800 that's Robert Louis Stevenson's Treasure
00:03:15.540 Island what is how is this on this shelf
00:03:18.180 I'm the child of a librarian this is so
00:03:20.519 embarrassing Miss shelving happening in
00:03:22.920 my own home
00:03:25.319 oh but it dawned on me of course this is
00:03:28.019 here of course because treasure maps
00:03:32.400 okay flowcharts
00:03:36.239 but think about it a treasure map is a
00:03:39.120 flow chart sure one of the core
00:03:41.220 strengths of a flowchart is the
00:03:42.900 branching the logic being able to map
00:03:45.420 out decisions that lead to different
00:03:47.280 outcomes but Stevenson's Captain Flint
00:03:49.860 only wants the happy path that ends into
00:03:52.319 doubloons
00:03:53.519 if we fill out the map we put a decision
00:03:56.640 Branch here at the edge of this dense
00:03:58.440 jungle without the map in our hands we'd
00:04:01.080 be lost in 404 not found
00:04:04.140 One Way lies treasure and the other to
00:04:06.599 an encampment of rival Pirates and 409
00:04:08.940 conflict
00:04:10.159 a decision here an East means treasure
00:04:13.739 but West means eaten by crocodiles and
00:04:16.320 just like that the whole crew is 410
00:04:18.600 gone
00:04:22.199 the rest of you need to brush up on your
00:04:23.639 HTTP status codes
00:04:27.060 not only is a flowchart useful for
00:04:29.040 retracing your steps to your long-buried
00:04:31.080 ill begotten gains but one of the most
00:04:32.880 helpful artifacts for understanding the
00:04:34.919 control flow of a system and invaluable
00:04:37.620 documentation for new team members it's
00:04:40.440 a kind of visual pseudo code think about
00:04:42.900 all of the low code and no code
00:04:44.940 solutions that are built on flowcharts
00:04:47.520 as a UI because they're so simple to
00:04:50.400 understand but potentially powerful
00:04:53.520 we can leverage that same strength as a
00:04:56.100 shared language to build understanding
00:04:57.900 between Technical and non-technical team
00:05:00.000 members and stakeholders and get buy-in
00:05:02.400 from the business in a way that we never
00:05:04.800 could with code
00:05:07.199 but no longer will the usefulness of
00:05:09.479 this tool stop at the code's Edge we're
00:05:12.000 going to learn how to directly apply it
00:05:13.860 to writing tests and eventually code
00:05:17.040 so consider yourselves horn swaggled and
00:05:20.100 snared into being my crew aboard the
00:05:22.139 Good Ship capybara on route to the
00:05:25.320 promised land where testing before you
00:05:27.240 leave Harbor can be smooth sailing
00:05:29.340 before this half hour be over we'll raid
00:05:32.160 the ship a knowledge and you'll have new
00:05:34.020 techniques of your own to boot
00:05:42.240 I do I do want to apologize for that
00:05:44.340 accent for everyone watching who is a
00:05:46.139 17th century Caribbean pirate
00:05:48.960 sorry privateer
00:05:52.380 a chart can relate fairly directly to
00:05:54.600 code serving to mimic the control flow
00:05:57.000 of an app but how it relates to testing
00:05:59.220 might not be as obvious we'll use a
00:06:01.620 pretty common situation of a rails
00:06:03.120 controller action to demonstrate how we
00:06:05.039 can take a handful of acceptance
00:06:06.660 criteria to a flowchart turn that into
00:06:09.300 test rigging test code and application
00:06:11.699 code
00:06:13.020 a couple of quick caveats and
00:06:14.580 definitions to simplify are upcoming
00:06:16.620 parlay
00:06:18.600 when I say feature I mean that to be any
00:06:21.360 unit of work be it a whole feature a bug
00:06:23.759 fix partial implementation whatever I'll
00:06:26.400 stick the same feature for brevity
00:06:28.740 there's also probably an actual term for
00:06:31.319 it but when I'm talking about a test
00:06:32.819 Suites rigging I mean the describe
00:06:35.400 context and it blocks that make up the
00:06:37.740 tests like here these lines with the
00:06:40.380 descriptive strings and the levels of
00:06:42.000 indentation that show how they relate to
00:06:43.680 one another that's what I'm calling the
00:06:45.479 rigging
00:06:46.979 and although this process will work with
00:06:48.840 any testing Library Ruby or not my
00:06:51.419 examples are going to be in our spec
00:06:53.039 because as we all know it is a pirate's
00:06:55.919 favorite testing framework
00:07:00.600 the app our team is building is called
00:07:03.120 Pirate Cove where freelance free booters
00:07:05.699 can list their available skills and
00:07:07.740 rating resume for captains looking to
00:07:09.960 round out a crew for upcoming misdeeds
00:07:13.319 sorry Adventures
00:07:16.139 our app has users we call them pirates
00:07:18.660 pirates have profile Pages it's off the
00:07:21.780 shelf uh rails resource routing with the
00:07:24.960 standard crud actions
00:07:27.960 this afternoon we're pairing all of us
00:07:29.819 don't worry I'll drive
00:07:31.979 and we've picked up a ticket with a new
00:07:33.599 user story
00:07:34.740 and it looks like it's to implement one
00:07:36.660 of those crud actions as a pirate I
00:07:39.360 should be able to fill out the form on
00:07:41.039 my profile page and submit it to change
00:07:43.020 my information
00:07:45.720 the acceptance criteria phrased a
00:07:47.940 different way so user can update a
00:07:49.680 pirate's information from the profile
00:07:51.360 page
00:07:52.319 there are actually two eventual
00:07:54.840 acceptance criteria or requirements on
00:07:57.300 this ticket but we're going to start
00:07:58.620 with just the first and pick up the
00:08:00.060 second as we go
00:08:02.160 so we're going to begin with the action
00:08:03.599 that we know is going to take place
00:08:05.340 that's typically a user acting on the
00:08:07.740 system and here that's our pirate
00:08:09.720 submitting form data
00:08:11.880 standard flowchart symbols have start
00:08:13.919 and end points as rounded shapes so
00:08:16.500 we'll start with that core action at the
00:08:18.120 top center of our workspace
00:08:20.099 when that gets submitted and action
00:08:22.080 occurs on the back end we're going to
00:08:23.759 save that data and how do we resolve
00:08:26.280 well we show the updated information
00:08:27.900 with a redirect to show
00:08:30.840 this alone right there that could be the
00:08:32.399 happy path of our feature we know it's
00:08:34.500 going to get a little more complex but
00:08:35.940 at least it's enough to write the
00:08:37.800 matching rigging
00:08:39.419 begins with a user action
00:08:42.899 some back end work
00:08:45.000 and feedback for the user beginning
00:08:47.100 middle end
00:08:50.220 now at the top of an R spec file we get
00:08:52.200 something like this to start but
00:08:54.000 everything we're doing is going to be
00:08:55.200 under patch update so this is the last
00:08:57.540 time we'll see this to say the save the
00:08:59.399 slides getting a little bit too
00:09:00.360 cluttered
00:09:02.040 right away I can see two outcomes that
00:09:04.500 we expect will happen after form data is
00:09:06.779 submitted by rails convention
00:09:08.760 redirecting to the pirate show page and
00:09:11.279 the only way that the pirate show page
00:09:12.660 is going to have the proper information
00:09:13.800 is if we also update the database to
00:09:16.500 reflect change data
00:09:18.480 this doesn't mean that every bubble in
00:09:19.920 the flowchart needs to be tested and
00:09:21.540 we'll see that coming up but in this
00:09:23.399 case we're testing more than just the
00:09:25.260 very end but also any action that
00:09:27.600 changes something outside of our current
00:09:29.640 test subject a side effect
00:09:32.339 our test subject is the Pirates
00:09:34.080 controller this makes a change in the
00:09:35.940 database way outside the controller
00:09:38.100 that's a result that we want to
00:09:39.720 guarantee will happen to the best of our
00:09:41.519 ability so we'll protect it with a test
00:09:45.480 that way if anyone ever comes along and
00:09:47.339 makes a change that affects that outcome
00:09:49.200 even if the redirect still happens we'll
00:09:52.140 have feedback then an expected result
00:09:54.360 has been affected that's our tests
00:09:56.940 preventing regressions
00:09:59.600 now the other piece to our test rigging
00:10:02.040 are contacts blocks the it blocks are
00:10:05.100 going to match up to the end results the
00:10:07.320 effects of the action the context will
00:10:09.480 correlate to the setups that exist those
00:10:12.060 are found by following each individual
00:10:14.040 path through the chart
00:10:15.899 pretty easy at the moment right now
00:10:17.399 we've only got one path through the
00:10:18.600 flowchart
00:10:20.399 it might make sense to wrap those two it
00:10:22.320 blocks in a context block
00:10:24.839 I don't think we actually gain anything
00:10:26.220 by doing that it's the only context that
00:10:28.620 exists and it's already Ratched wrapped
00:10:30.839 in that patch update describe block so
00:10:33.420 personal preference but I'd leave it off
00:10:35.339 for now
00:10:36.839 what else this indicates by being only
00:10:38.700 one context is that our setup for these
00:10:41.040 two tests will be the same
00:10:43.140 each individual path through the chart
00:10:45.000 will have a different state when the
00:10:46.860 action is performed we're focused on to
00:10:49.019 a level where there is only one action
00:10:51.720 and most of the time that you're
00:10:53.279 building out tests that's how it's going
00:10:55.260 to be maybe different granularities
00:10:57.360 sometimes different params or callers
00:10:59.279 but one single inciting action
00:11:02.459 in the ideal State when you're focused
00:11:04.200 on testing just one action the only way
00:11:06.540 to take different paths through the
00:11:07.920 chart is with a different beginning
00:11:09.180 state or different params to that action
00:11:14.040 so we're still here we kind of know that
00:11:17.160 it's not going to stay this simple and
00:11:18.720 this is a position you might find
00:11:20.040 yourself in pretty often you know that
00:11:22.200 there's more looming but it hasn't
00:11:23.880 actually shown up quite yet
00:11:26.279 so that's not complicated I'd rather
00:11:28.200 start moving forward on something that
00:11:29.579 I'm sure of naive or not rather than
00:11:32.100 speculate and end up down in irrelevant
00:11:34.320 rabbit hole
00:11:35.940 as I said irrelevant Rabbit Hole okay
00:11:38.760 we've got some ambiguity but we've also
00:11:40.860 got something concrete so let's move
00:11:42.779 forward on that I'm confident enough
00:11:44.579 that what comes next will reveal itself
00:11:46.560 as we go through this exercise or if it
00:11:49.500 doesn't it could be outside the scope of
00:11:51.959 what we're trying to accomplish right
00:11:53.339 now plus I want to err on the side of
00:11:55.620 shipping software rather than analysis
00:11:57.959 paralysis
00:11:59.519 and really this is the whole happy path
00:12:01.980 right if nothing goes wrong this is
00:12:04.380 essentially what needs to happen so if
00:12:06.779 we write these tests we'll have a North
00:12:09.000 star to guide us as we sail along and
00:12:11.700 seas get choppier if we ever make
00:12:13.740 changes and these tests fail we should
00:12:17.160 probably do some rethinking
00:12:19.200 our new tests will be preventing our own
00:12:21.959 regressions that's just another reminder
00:12:24.240 that the next developer to work with
00:12:26.339 your code can be ourselves even just an
00:12:30.000 hour later
00:12:32.040 so should we write some tests
00:12:34.500 okay before that
00:12:36.779 um I'm also not here to introduce or
00:12:38.339 debate the different methodologies for
00:12:39.959 writing individual tests that's another
00:12:41.459 talk or workshop and they mostly all
00:12:44.160 boil down to some variation of given
00:12:46.200 when then
00:12:48.720 what might test code for this portion of
00:12:50.579 our rigging look like
00:12:52.079 let's start with the setup we know we
00:12:54.180 need a pirate whose information is going
00:12:55.620 to be updated and whose ID will be part
00:12:57.720 of the URL based on Rails restful
00:12:59.760 conventions
00:13:01.260 and now the action we already said
00:13:03.180 that's going to be when the user submits
00:13:05.339 the form data so if we use rspec's
00:13:07.680 request syntax it might look something
00:13:09.660 like this
00:13:10.920 and eventually our expectation that
00:13:13.500 should redirect
00:13:15.899 here we are with test code for both it
00:13:17.820 blocks from before redirects to the
00:13:19.860 user's show page and updates the
00:13:21.839 database
00:13:23.399 now we've got some wind in our sails
00:13:25.380 we've understood our flowchart as a
00:13:27.360 context and still at Just One path our
00:13:30.060 given is the matching setup
00:13:32.940 the action that begins our flowchart has
00:13:34.980 become the when that's the action taken
00:13:37.320 in our test cases
00:13:39.660 and we've identified the two end States
00:13:41.639 one for the hdb response and one for the
00:13:44.820 database
00:13:46.560 and we've captured them as then in the
00:13:49.500 expectations
00:13:52.200 so as I'm building out a system I'm
00:13:54.240 trying to uncover moments where we might
00:13:56.100 be taking something for granted an
00:13:58.380 assumption that we've built on top of
00:13:59.940 that isn't as guaranteed as we're
00:14:01.680 treating it so I'm asking myself what
00:14:04.320 here is built on a lie
00:14:06.839 what here could go wrong and my eye is
00:14:09.420 drawn to this
00:14:11.579 these params are sent in by a user
00:14:14.519 you know users so do I no I don't trust
00:14:18.300 them
00:14:19.740 they always find
00:14:21.839 interesting ways to stress the system
00:14:24.240 brand new ways to use our software that
00:14:26.399 we never even dreamed of
00:14:29.220 in reality though that's a gift it
00:14:31.320 really is and I believe that but right
00:14:33.120 now it's a problem
00:14:35.279 so far our tests are assuming that
00:14:37.200 everything is going to go smoothly we
00:14:39.360 need to handle what happens when the
00:14:40.920 params don't pass validation
00:14:43.320 so let's fold up the test code like
00:14:44.880 we're in our editor and add this params
00:14:46.740 protection what would params that don't
00:14:49.079 pass validation change about the flow of
00:14:51.660 this chart
00:14:54.139 right that change will never make it to
00:14:56.880 the database and because that can fail
00:14:58.980 we need to add to the flowchart before
00:15:00.720 the persistence a check for validity
00:15:03.360 we'll notate this fork in the road with
00:15:05.519 a diamond because in flowchartland which
00:15:07.500 is a province of diagramopolis a diamond
00:15:09.720 represents a decision
00:15:11.639 something in the setup or the action
00:15:13.800 that is affecting the outcome
00:15:16.199 the value of which decides the branch of
00:15:18.600 the flow to continue down and now we
00:15:21.240 truly have more than one path through
00:15:22.800 the feature and with it another context
00:15:25.380 that needs testing
00:15:27.180 let's trace the two paths so we can see
00:15:29.100 what we're dealing with
00:15:31.680 if a path is a context we're able to
00:15:34.680 tell that one context is separate from
00:15:36.720 the other the nodes in the flow chart
00:15:38.699 that are reflected in the rigging as
00:15:40.560 existing specs can't be reached by that
00:15:43.260 New Path they're an entirely different
00:15:45.240 context
00:15:49.740 let's reflect that in the rigging
00:15:52.500 but how can we know what that context
00:15:54.120 involves it's not as simple as an
00:15:56.160 endpoint there isn't one node in the
00:15:58.199 flowchart that equates to context but
00:16:00.420 many along a path
00:16:02.279 so let's ask ourselves a question what
00:16:04.560 given what setup or initial input will
00:16:07.980 cause the decision to go to the right
00:16:09.660 where we see the two it blocks that we
00:16:11.699 already have
00:16:13.620 valid params right
00:16:16.800 and then the opposite invalid params
00:16:19.380 causes the flow to go to the left
00:16:21.959 and the it block based on Rails
00:16:23.639 conventions will render that render the
00:16:25.620 edit page again and send the object over
00:16:27.360 to The View with those validation errors
00:16:29.160 attached
00:16:30.660 so let's act on these tests in the
00:16:32.579 flowchart as we have it currently what
00:16:34.680 do we want to do next personally I'm not
00:16:37.139 going to feel good about these tests
00:16:38.339 until I see them fail we haven't written
00:16:40.440 any code for them yet so if they pass
00:16:42.420 there is definitely something fishy
00:16:44.339 going on
00:16:45.839 great news the test failed
00:16:48.240 that means we can write some code to
00:16:49.680 make them pass
00:16:51.779 we're going to keep this as simple as
00:16:53.100 possible but let's think about the code
00:16:54.480 that we'll need in order to follow the
00:16:56.100 flowchart and satisfy the tests
00:16:58.440 we'll need to know which pirate
00:17:01.019 if the update works we'll redirect
00:17:05.220 and if not we'll render edit nothing
00:17:07.439 fancy here this is direct from rails
00:17:09.360 generators maybe condensed a little for
00:17:11.459 slides but how did our tests fare
00:17:15.299 nice good work everybody
00:17:19.020 let's just take a moment to reflect on
00:17:21.120 how we got here we use the ticket
00:17:22.980 requirements to make a simple flowchart
00:17:25.260 that met the user story The Happy path
00:17:28.559 and from that flowchart came our test
00:17:30.419 rigging
00:17:31.500 we wrote some tests and uncovered a
00:17:33.480 failure state
00:17:34.620 which led us to expand on our flowchart
00:17:37.320 and rigging
00:17:39.240 and from there we used our understanding
00:17:40.980 of the system at play to write the
00:17:42.720 application code
00:17:44.760 chart rigging test
00:17:48.179 chart rigging code
00:17:51.840 all that is to say that this process
00:17:53.460 isn't going to be linear most of the
00:17:55.260 time usually we won't have written the
00:17:57.600 whole entire flowchart with everything
00:17:59.280 in scope then move on to the entire
00:18:01.320 rigging then the test code then the app
00:18:03.840 code will bounce around acting on the
00:18:06.240 next bit of information that we're
00:18:07.559 confident about uncovering assumptions
00:18:09.720 as we go and adding to our framework in
00:18:12.240 the process
00:18:14.120 well we don't really have everything
00:18:16.679 that's in scope do we remember that
00:18:18.960 there is a second acceptance criteria
00:18:22.080 number one we already have we can update
00:18:24.840 a pirate's profile info but two here
00:18:27.720 says that only authorized Pirates can
00:18:29.640 perform updates
00:18:31.559 so before I check for validity in the
00:18:33.600 same way that we added the valid step
00:18:35.700 before persistence
00:18:37.620 we have a new Step that can interrupt
00:18:39.539 the process before reaching the end
00:18:41.039 states that we had charted before
00:18:43.799 which leads to another path through the
00:18:46.260 chart
00:18:47.280 now ignore for now the implementation of
00:18:49.679 even having a logged in user I've only
00:18:51.419 got actually got 11 and a half more
00:18:53.100 minutes with you but no
00:18:55.820 another path should make us think what
00:18:59.039 another context
00:19:01.440 using the same technique that we did
00:19:03.240 before we can wrap the expectations
00:19:05.100 based on when their paths diverge the
00:19:08.280 first time any paths diverged they go in
00:19:10.320 two different directions
00:19:11.940 green to the left
00:19:13.740 blue and orange to the right
00:19:16.320 so that tells us that there will be two
00:19:18.000 contexts and it's the decision where
00:19:20.280 they branch that tells us what that
00:19:22.260 context is
00:19:23.880 authorize no that's green
00:19:27.539 and because the other paths share the
00:19:29.400 state of a pirate that has permissions
00:19:31.620 to change this data
00:19:33.480 the context about being authorized will
00:19:36.539 wrap them both
00:19:39.960 but we've done this kind of exercise
00:19:41.400 before earlier I bring it up again
00:19:44.100 because I want to throw a metaphorical
00:19:46.080 match in our powder keg
00:19:48.480 turns out what makes someone authorized
00:19:51.480 isn't so cut and dry authorized yes no
00:19:54.720 it's perfectly fine for the flow chart
00:19:56.400 here because at the controller level
00:19:58.440 that's the flow of this action
00:20:01.500 but to be authorized while the logged in
00:20:04.140 Pirate is either the pirate being
00:20:05.880 changed or a pirate with the admin role
00:20:10.200 what was once three paths through the
00:20:12.360 chart is now five and if we reflect that
00:20:14.640 in the test cases we go from four to
00:20:17.520 seven that's 57 more tests and I like
00:20:21.240 tests and all but conceptually this
00:20:23.520 doesn't feel too much different from
00:20:25.020 what we already had
00:20:27.840 we added this section but it makes the
00:20:30.720 same decision authorized yes no it's
00:20:34.020 just a more complicated process
00:20:36.179 maybe you're already standing where I'm
00:20:38.640 leading you or maybe you're on the way
00:20:40.020 but if this box was opaque
00:20:43.679 and all we saw was authorized yes no
00:20:47.460 then the rest of the paths would have
00:20:49.200 the same information in the same flow
00:20:51.780 right
00:20:54.240 does the pirate controller really need
00:20:56.280 to know how to tell if a pirate can make
00:20:58.559 the change or does it just need to know
00:21:00.660 whether to make them walk the plank or
00:21:02.280 not
00:21:03.600 it's the latter right
00:21:05.580 so let's encapsulate that logic in an
00:21:08.100 object look at this Robert Louis
00:21:10.320 Stevenson Sandy Metz back together after
00:21:12.660 all this time
00:21:15.120 and because we can test the
00:21:16.620 authorization logic over in this
00:21:18.720 object's tests some might even call it a
00:21:21.059 service object it doesn't have to be
00:21:23.100 part of our controller test at all we
00:21:25.500 can mock the call to the service object
00:21:27.299 within the test force it to say yes or
00:21:29.520 no all a part of our setup and suddenly
00:21:31.980 we're back with just authorized yes no
00:21:34.860 and the next time that you're looking to
00:21:37.080 encapsulate some logic away in a service
00:21:39.480 object look for parts of your flow chart
00:21:41.880 where those paths go apart do something
00:21:44.059 self-contained but then converge back
00:21:46.559 together like we did here
00:21:48.539 but if we think about it
00:21:50.340 we already have similar nodes in this
00:21:52.980 flowchart don't we
00:21:55.580 right there
00:21:57.539 this isn't a single thing this is active
00:22:00.480 record taking our params hash doing
00:22:02.400 something with ARL spitting out SQL
00:22:04.980 traversing to a database which is a
00:22:06.840 whole different program updating a
00:22:08.460 resource can you imagine the flowchart
00:22:10.260 on that
00:22:11.820 an active record just handles it so we
00:22:14.280 can put a single box in our flowchart
00:22:17.220 in the same way that we zoomed in to get
00:22:19.740 to an authorization service class and we
00:22:22.260 understand the zooming we could do
00:22:23.940 behind the persist node we can also zoom
00:22:26.520 out from our controller
00:22:28.860 up until this point we've been looking
00:22:30.539 at a single action and everything else
00:22:32.460 happens like dominoes without our
00:22:34.620 influence
00:22:35.820 this is a flow chart for ordering a book
00:22:37.980 from Amazon
00:22:40.020 uses very high level it's really zoomed
00:22:42.120 out it's all the way to the user
00:22:43.320 everything is abstracted away they're
00:22:45.480 not thinking about HTML servers
00:22:47.580 databases none of it and yet this is an
00:22:50.760 incredibly useful diagram even for
00:22:53.340 testing even for writing code
00:22:56.220 in the same way that our happy path
00:22:58.320 tests were our North Star while building
00:23:01.140 and refactoring something like this can
00:23:03.240 be the North Star for an entire business
00:23:05.220 or development team able to ask
00:23:07.500 themselves can a user still order a book
00:23:09.799 or does this help a user order a book
00:23:14.340 probably not Amazon anymore because
00:23:16.440 nowhere on here do I see shoot founder
00:23:18.299 into space
00:23:20.880 I also don't see let him come back
00:23:22.559 either but we did that
00:23:26.460 each of these purple blocks is an action
00:23:28.440 by a user sign in add to cart each and
00:23:31.980 every one of them probably could be its
00:23:34.260 own controller action if it was rails
00:23:36.120 each with its own flowchart as intricate
00:23:38.640 but probably more so than the one that
00:23:40.799 we just built but at this level this can
00:23:43.559 a user order a book level
00:23:46.080 those aren't important for the same
00:23:48.240 reason that it wasn't important to our
00:23:49.919 controller if the user was an admin or a
00:23:52.620 specific pirate
00:23:54.179 still each branch or each flow is going
00:23:56.820 to need a test maybe at this level a
00:23:59.220 context maybe not again personal
00:24:00.900 preference but I see five six tests here
00:24:05.419 eventually every purple box reached by
00:24:08.159 the path of a test from start to end
00:24:12.299 so I I hope that helps you see that
00:24:14.940 there aren't rules on how to do a
00:24:17.280 treasure map technique but some ideas
00:24:19.860 and advice on how you might be able to
00:24:21.900 apply it in your own work I literally do
00:24:24.840 this in my work this is a commit message
00:24:27.840 I wrote last week
00:24:30.840 that's right I know
00:24:34.200 I put the flow chart in the commit
00:24:36.840 message
00:24:38.700 and if you two want your commit messages
00:24:40.559 to bring all the boys to the yard
00:24:45.480 the tool I use to make this plane checks
00:24:47.940 plain text flowchart is ASCII flow
00:24:50.400 that's askiflo.com so yeah take these
00:24:54.000 ideas use them throw away what isn't
00:24:56.760 working add on where it falls short
00:25:01.020 oh okay and if you do add on or do
00:25:03.600 something cool with it please please
00:25:05.039 tell me on the twits the gram GitHub any
00:25:07.860 of these things I'm around
00:25:09.659 I would love to know how you remix this
00:25:12.240 or adapt it to other Frameworks and
00:25:14.220 languages it's open source this thing
00:25:16.140 right
00:25:17.100 because
00:25:19.500 our we might be here under the auspices
00:25:22.140 of land Lovin rails rather than ocean
00:25:24.960 waves I can without objective see
00:25:28.320 whether your features be crafted a ruby
00:25:31.020 Emerald carved of elm adorned with Jade
00:25:34.799 and pearl are crested in Rust are this
00:25:38.940 Elixir flies truthy as a dart for all
00:25:42.059 those who sail the sea from java to
00:25:44.400 Ceylon
00:25:46.140 in lieu a more formal ER language
00:25:51.179 and you might consider it basic but even
00:25:53.520 through a common lisp I won't be here in
00:25:55.679 any small talk because this ship to be
00:25:58.200 Swift as an O camel traveling the mighty
00:26:00.960 go B desert
00:26:08.760 but to give
00:26:13.260 I am particularly proud of that one but
00:26:15.480 to give this here groovy assembly some
00:26:17.880 unity and closure let me be crystal
00:26:20.460 clear with the AL gold to Davey Jones's
00:26:23.279 locker and Bash a hundred foot python
00:26:25.500 before I give up me test driven
00:26:26.940 development
00:26:28.140 and now that you've seen the ample
00:26:30.240 scholar this technique
00:26:32.100 I hope your acceptance criteria ever be
00:26:34.740 clear your test Suite not Scuttle your
00:26:37.500 deployment and the cloud never take the
00:26:40.020 wind out here sails so that the Good
00:26:42.179 Ship capybara can see you home
00:26:45.900 thank you