RailsConf 2013

TDD Workshop: Outward-in Development, Unit Tests, and Fixture Data

By Harlow Ward & Adarsh Pandit

thoughtbot are creators of the open-sourced testing tools FactoryGirl and Shoulda Matchers.
We recognize Test-Driven Development (TDD) can be difficult to practice as features increase in complexity. Testing is often skipped when developers feel uncomfortable with TDD or have not yet seen certain approaches in practice.
We'll describe specific techniques used in TDD which touch on: Integration testing with RSpec+Capybara, Model Associations and Data Validations, Asynchronous Jobs, Emails, 3rd Party Services, and JSON API endpoints.

Help us caption & translate this video!

http://amara.org/v/FGan/

RailsConf 2013

00:00:12.259 thank you hey everybody
00:00:18.900 welcome I'm others Pandit this is Harlow I'm Harla Ward
00:00:25.320 and we are both from topot and today we're going to do a giant group pairing
00:00:30.960 exercise where we're going to walk through how to do test driven development
00:00:36.260 there's some prerequisite stuff up here if you haven't had the chance to clone the repo please do so if you have
00:00:43.379 trouble please raise your hand we have a number of awesome Tas who are running around who will help you there are also
00:00:50.539 your neighbors nearby many of you have paired already and that's great so
00:00:56.940 please help one another out this is a workshop setup so we're going to do some live coding and you know you guys can
00:01:03.660 follow along I'll talk a little bit more about that in a sec we have a USB stick now too with all of
00:01:09.840 the gems on it so if you're still struggling with it uh raise your hand at some point one of our guys will come
00:01:14.880 over and get you all set up so we've got some folks right here on the aisle
00:01:21.000 yeah okay great so this is who we are uh we're both
00:01:26.820 developers at thoughtpot this is where you can find us on email and the Twitter
00:01:36.000 and uh we work for thoughtbot thoughtbot is a rails consultancy and iOS
00:01:41.579 we have developers and designers and wonderful iOS developers we build
00:01:47.579 startups and for the mobile and the web and it's a lot of fun we also have a lot of
00:01:54.540 gems open source gems and tools that we manage and you can find them all at thoughtpot.com community
00:02:01.439 and this is Ralph the robot in ASCII art
00:02:07.560 okay so some housekeeping stuff we're going to do a two-part Workshop
00:02:13.220 initially this might have been described as one half talk and one half Workshop
00:02:18.239 but we figure we're just going to be showing code anyhow so we're going to do this as a giant workshop and what that means is
00:02:24.900 we're gonna be demonstrating we'll be demonstrating code up here
00:02:30.959 Harlow and I are going to pair and you guys can code along out in the audience so in our typical
00:02:37.520 workday if we're working on some client work um pairing we'll be doing what we call
00:02:42.840 Ping Pong where I'll write a test of fails otter shall write some code to make it
00:02:47.940 pass he'll write the next failing test comes back to me and so we'll go back and forth like that it keeps a set of
00:02:54.900 eyes on it and it's a nice during the refactoring phase that you're quite often refactoring someone else's code
00:03:00.599 which is great to have that second set eyes yeah exactly
00:03:06.300 um many of you are of different levels of experience this is probably best for somebody with some rails experience
00:03:13.560 although in our experience we found that even
00:03:18.599 exposing yourself or watching things that are over your head will allow you to make some notes on things to look up
00:03:24.780 later and some of it may make sense to you further on down the line so definitely don't get dissuaded there's a
00:03:31.860 lot of complex stuff we're going to go over and if you have questions please let us know
00:03:38.580 I think that's right and it's and it's really um my main goal of this talk is to hopefully expose a few of the techniques
00:03:45.659 that we've been using over the last couple years um things that when I started developing in Ruby
00:03:51.840 um it can be a bit of a hurdle not knowing how to test something so these are some techniques we've learned over the last
00:03:57.420 couple years of how to test certain scenarios that may seem Troublesome up front
00:04:04.799 so in terms of format we're going to we have a bunch of different modules which we'll walk through
00:04:11.879 we'll introduce a topic like integration testing and then we'll talk about it for
00:04:17.400 a few minutes then we'll actually live tdd the feature so that's sort of how we're
00:04:24.240 going to go through it and in between we'll stop for comments or questions and this is meant to be very interactive so
00:04:30.000 if you have questions you know let us know comments any of that
00:04:36.300 yeah there Shadow questions as you have them your neighbors are also super useful
00:04:42.180 we definitely encourage you guys to pair we're going to simulate the pairing experience up here to give you a sense
00:04:47.400 of what that's like it's the best way in our opinion to learn how to be a developer and to learn Ruby
00:04:54.720 or rails or anything just to share a computer you pick up so much just in the shared experience
00:05:02.580 and we have a number of Tas as I mentioned running around wearing thoughtbot oriented gear can you guys
00:05:07.800 raise your hands where you're up there we are so take a look around if you have any issues these guys can come and help
00:05:13.440 out Caleb is confusing her hand raising
00:05:19.380 setup so we're going to have the the
00:05:24.419 thoughtbot repo which you guys forked we're going to commit to that as we're
00:05:29.460 doing our work and so you can refer to that and see the code that we've committed Wi-Fi permitting and that way
00:05:37.500 you can follow along and you can also commit to your own forks and have a record of how this went for you guys and
00:05:43.800 you can do a compare and contrast
00:05:50.520 right so the the main goal here is to to write our tests first and the the
00:05:56.940 thought here is that with writing the test first we're going to get the code that we need for this feature in and
00:06:03.479 hopefully not more um so we have a smoke test app that you
00:06:08.880 guys have all got running locally here it's a really basic to-do's application
00:06:13.919 um right now you should be able to run the test Suite that test Suite demonstrates
00:06:18.979 creating a to-do and our next step is going to be writing
00:06:25.020 some code to be able to complete these to do's
00:06:30.060 so when we talk about test driven development raise your hand if you're familiar with test driven development
00:06:37.020 know what it means okay great raise your hand if you practice test driven development
00:06:43.139 all right keep your hand up keep your hand up if you practice test driven development a hundred percent of
00:06:48.780 the time all right great you're in the right place a lot of part of our talk title use the
00:06:56.160 word discipline and that's really what it takes it takes practice and discipline and we'll show you a little bit of how we
00:07:02.400 do what we do and show you test driven development I think seeing it is a lot easier than learning
00:07:09.539 it out of a book so wherever possible see someone or meet somebody who's better than you and at test room
00:07:16.080 development and pair with them that's a great way to learn
00:07:22.620 so some of the benefits I'll just skim through these since everybody seems to be fairly familiar with them uh you set the expected outcome first
00:07:30.960 it forces you to consider the purpose of your code before you write it which I
00:07:36.780 think is very important otherwise you can end up on what I call a jazz Odyssey of coding
00:07:41.880 where you're kind of Meandering around it reduces bugs and rework
00:07:49.259 it tells you as you're developing if something you've done has changed or broken something else
00:07:56.639 it serves as a form of documentation that lives on in the repository and instructs other developers as to what
00:08:03.780 your code actually does and is everybody familiar with the red
00:08:10.979 green refactor cycle okay so I'll touch on that quickly so
00:08:16.020 what that means is red and green refer to the color of the test outputs so if your test fails it's red and if
00:08:23.879 it's green it passes and we the term red green refactor we
00:08:30.479 actually treat a little more like red red red continuous red until you get to that green and we really let the test drive
00:08:37.979 the code that we're adding um so the test will assert something it's a feature so there's there's
00:08:43.800 multiple assertions kind of on the way here and we'll add elements to the code base we'll kind of let the test drive us
00:08:51.300 to the passing code yep so let's get into it
00:08:57.480 I'm going to lead us off yeah absolutely first section
00:09:08.480 so part of the the pairing experience is about communication and
00:09:14.519 talking through problems with your pair so we're going to alternate
00:09:19.920 who's going to be writing code and tests and so Harlow's going to be typing for a bit
00:09:25.320 and then we'll swap places and it's it'll give you a feel for roughly how we typically will pair
00:09:32.160 why don't we walk through the kind of smoke test that's in place right now yeah make sure that we all
00:09:39.480 kind of understand what's Happening Here um add a task yeah that sounds good
00:09:45.660 so um this is for those of you who were around yesterday and saw the R spec
00:09:51.000 capybara talk doing integration testing really what that means is integrating your full web
00:09:57.839 application stack and testing it as a unit there are a number of ways to do it but
00:10:03.480 really what you're doing in the old days was writing a script and saying
00:10:09.600 to some poor person who you're paying to do this repeatedly you know log in as Joe Smith add this
00:10:16.380 password and make sure that everything works nowadays we have automated browser testing with capybara or cucumber and so
00:10:24.060 on so we're gonna the model we're gonna use is our spec capybara which is what you might have seen yesterday
00:10:31.080 I think this has been a we were using cucumber for a long time and I think the new DSL with capybar has been a win for
00:10:36.839 us so we kind of have this feature scenario which comes with capybar 2.0 um so the way that we write these tests
00:10:43.680 now feels a lot like we were writing as far as the Cucumber features go
00:10:49.260 um but I feel like with the R-Spec integration tests we're a lot closer to the capybar steps now which feels pretty
00:10:56.399 natural as you're working in a code base yeah so these are the tests that you already have in your repository so the the file name
00:11:04.140 will be down here but I'll tell you what it is this is vim for those of you who are Vim enthusiasts like many of us at
00:11:10.019 botbot this file is in Spec features user manages tasks underscore spec dot
00:11:17.700 RB so just to show
00:11:22.800 um so we're going to add a new feature right and the what we have for the
00:11:29.339 application uh can we spin up the the server and show it quickly sure
00:11:36.300 so this application is dead simple it should be easy to follow it's a to-do
00:11:41.760 application like every learning application all you can do is you sort of create
00:11:47.399 read or create edit and destroy some to some task
00:11:54.300 so it's pretty simple
00:11:59.700 it looks like this so we can click new task
00:12:05.940 and for those of you who are not familiar with what we did here we type rails server at the prompt
00:12:11.640 and they went to localhost 3000 or you can set the port to 5000 in this case
00:12:17.820 so what Harlow did was just add mow the lawn as a task and then hit create a task and then it
00:12:23.820 went back to our index of all the tasks so super simple crud application at this
00:12:29.220 point um and now we want to do is add the ability
00:12:34.680 to complete a task we probably won't use the web browser
00:12:40.500 again and I encourage people not to unless you're troubleshooting something that uh that you can't figure it out
00:12:46.740 through the terminal but most of the time we'll be in the terminal looking at the failed steps and then
00:12:52.320 fixing from there it's it becomes a little bit it's a little awkward at first not being
00:12:59.519 in the web browser but your productivity goes up over time being able to work
00:13:04.860 directly out of the terminal everything's closer so for those of you familiar with
00:13:10.800 cucumber we use some similar nomenclature scenarios and features so
00:13:17.040 this whole feature if we go to the top is called user manages
00:13:22.560 tasks and the scenario we want to write is Mark the task as complete
00:13:30.120 so we can use capybara's syntax to drive a browser around so in this case what Harlow's doing is
00:13:36.600 he's setting a task name
00:13:43.019 that's exactly right and the copy bar DSL we put some kind of cheat sheets
00:13:48.839 their PDFs in the main repo links to them and that'll give a nice overview of all of the actions you can take using
00:13:55.860 capybara you have the option to fill in the name field click buttons
00:14:01.139 et cetera there so I think I might have so I think in line 25 we need an equals task
00:14:07.500 underscore name equals Mobile on correct unless that's a method that you
00:14:13.440 just wrote so we did as we said scenario Mark task
00:14:20.040 complete we made a variable with the fake task name
00:14:25.139 that we wanted to use line 27 we said visit root path which
00:14:30.540 means go to the root in the browser click Link new task so Cafe Bar will
00:14:38.399 look for this any kind of link with this text in it if there's more than one it'll complain It'll ask you to be more
00:14:44.639 specific you can actually if it's within a div or a span excuse me you can specify that
00:14:52.440 then for forms you can type fill in and then again you specify the field
00:14:57.720 name so here it would be name with and then the task name that we set up at the top
00:15:05.220 and then we click the button create task so this is just a script that mimics
00:15:10.260 what we just showed in the browser that's exactly right so we're doing a
00:15:16.380 so part of the process here is we're going to kind of write the code to get this to pass and you'll notice that we're adding a bit of duplication in
00:15:21.839 here and that'll be part of the refactoring step where we treat the testing the test code base just like we
00:15:29.339 would the regular code base and we'll show some techniques for stripping and duplication from that area there too
00:15:35.180 so what I'm hoping to do right now is write a failing test that makes me add a
00:15:42.139 complete task button to the interface and then that will kind
00:15:49.199 of demonstrate how we go forward and add code to the views
00:16:00.480 so what Harlow's doing here is what I had mentioned earlier so Within this HTML element
00:16:07.800 we're looking for specific
00:16:12.860 a specific tag so we're hoping at the TD which is the list element or
00:16:20.699 the sorry the table element when it contains the task name
00:16:25.920 what we want to do is Click complete so next to so we're setting an expectation here which doesn't exist in our
00:16:31.500 application and that expectation is next to every to do we want a link that says complete
00:16:39.779 and then here at the bottom we're going to write an assertion that says okay well we expect
00:16:45.000 that we won't have this link any longer and one thing you might note is that we put
00:16:51.360 some new lines here at line 30 and 34. just as a matter of style we like to separate the phases of the test so there
00:16:58.920 are four phases to the classic test it's set up setup exercise assert and then tear down
00:17:07.679 so the setup is everything you do before the thing you want to test the exercise is the actual thing that
00:17:13.439 you want to test the assertion is an active assertion that says I expect this thing to have
00:17:20.400 happened I expect to be logged in and so on and then the tear down at least in our respect is actually done in the
00:17:26.640 background so we don't do that as explicitly and then if you notice here when I'm
00:17:31.980 running this test with rspec um where
00:17:37.740 we're pinpointing the file directly and using a colon you can specify the line number of the test
00:17:43.799 and that could have been any line between 24 and 36 and that way as you're
00:17:51.419 working on a specific feature in your app you can just run that particular test at
00:17:57.120 the end of the task we'll want to run all of the tests to make sure we haven't broken anything but this allows your tests to run more
00:18:03.299 quickly and hopefully a little bit isolation here so for those of you who can't see it
00:18:08.520 at the bottom when we run a test is our spec and then the file name and then here we we did colon and then
00:18:15.720 the line number
00:18:21.059 you can see that here our spec spec features user manages tasks colon
00:18:26.340 24. so then we only run that test if we left off the colon 24 run the whole test
00:18:32.880 do you want to get in here and make this pass yeah
00:18:44.940 see if I can do it
00:18:59.400 okay any questions so far on the DSL or
00:19:05.400 the code up here okay so FD is a flag on rspect which is
00:19:11.039 format in documentation mode when I'm running a single test I kind of like that it'll kind of show you which
00:19:17.340 assertions failed in English when we run the whole test Suite we'll take off the FD and then you'll just get the dots
00:19:22.679 which is kind of the progress run so the essence of tdd is to let your errors
00:19:28.020 Drive what you're doing so I'm looking at this error and it says
00:19:33.539 failure error within TD contains task name do no quick here at CSS syntax error unexpected space after MO
00:19:43.140 uh do you think there's an error in having a space for our task name
00:19:48.480 is that what's going on there
00:19:56.700 good question um do you want to fire up the
00:20:01.980 let's see here also just to set expectations we will be
00:20:08.940 making mistakes and crumbling through things along the way this is part of the joy of tdd
00:20:18.200 definitely not so why don't I try a task name that has
00:20:25.200 no spaces we should be fine because I'm 16 there we have a mow the lawn task already
00:20:31.799 visiting the root path new task fill in name with task name click button create task
00:20:40.919 yes
00:20:52.200 marked for all completed tasks so it seems like the step before actually
00:20:58.080 writing the test is sitting down and saying how are we going to structure it
00:21:03.660 and then saying how are we gonna test it's a great Point absolutely I mean
00:21:10.380 oh sorry so the the comment question was um
00:21:16.080 some thought has gone into this before writing the test and that
00:21:22.200 we're going to test that there is a flag or a class on this TD here that is
00:21:27.900 completed quite often that'll be a designer we're working with adding a class name in the
00:21:34.679 HTML but we'll try to work together and communicate kind of what happens on the front end
00:21:40.980 HTML but you're absolutely right that that I think part of the great part of writing these tests is it
00:21:47.280 kind of makes you think about the user's flow up front before you actually write any code into your application
00:21:57.179 I struggle with um I sit down to write tests and I'm not really sure what
00:22:02.820 how it's going to end up so when you say um so so you struggle
00:22:10.080 with sitting down and you're going to write test but you're not sure how they're going to end up um do you have a like a definition of
00:22:16.380 the feature that you're trying to accomplish I think that's usually a nice way to think about the code that you're going
00:22:23.460 to write so when we write these scenarios we try to write them with an actor and then what they're going to do
00:22:28.919 on the system so for example here this feature is user manages their to-do's so
00:22:36.059 that's a very limited scope to this test now right and then within there we'd have a scenario maybe adding a task
00:22:41.940 editing a task if that's possible completing the task um
00:22:48.900 doesn't make sense okay cool I found the bug so within the task name that needs to be in
00:22:54.600 single quotes ah okay that makes sense all right so now our error says failure
00:23:01.140 error click link complete Cappy bar element not found unable to find link complete so what that means is we have
00:23:07.860 to make a link that says complete so we're going to put that in our view
00:23:14.220 that sound right that sounds right so we'll go into view
00:23:20.580 let me do this the full way app views tasks
00:23:26.940 and then this would be hiding under index
00:23:33.960 so we have a render here which is rendering all the tasks so we'll have a partial which should be underscore
00:23:39.780 task which will have the individual tasks and the HTML surrounding them
00:23:46.919 so I'll go into the partial here and again this is app views tasks
00:23:52.320 underscore task dot HTML so now we have the task name
00:23:59.340 and let's add a complete link
00:24:05.460 so he's going to write the minimum amount of code to get this Test passing now
00:24:11.280 so I'm going to move this TD tag to the end
00:24:21.659 so task or I guess link to
00:24:27.960 complete so we're going to want to send this to
00:24:33.419 an action and in this case I think we should use a separate controller does that sound
00:24:40.020 right I like that okay so let's call it the task completions path
00:24:48.480 and again here we're writing the code that we wish we had so what we're saying here is we're going to create a new controller called
00:24:55.080 completions and we're going to post to that and so when someone posts to the completions
00:25:01.380 controller it'll Mark that particular task as complete
00:25:06.539 this is a Technique we use quite often to really be explicit about the action
00:25:13.559 that's happening here so let's run the test again
00:25:28.559 okay great so the tests are guiding us here it's telling us we have an undefined
00:25:34.559 method task completions path that means that we're missing a route
00:25:40.679 so now this will force us to jump into our routes file add a new route for the task completion
00:25:53.340 so we should probably Nest this I think So within each task it should have
00:26:01.020 that's exactly right so we'll need a nested route here so we can grab the task ID out of the URL
00:26:06.059 and then in the I guess it'll be the create action we can then pull that out
00:26:12.840 in the params so there's a route
00:26:20.520 if I type that right I'm just going to clear the screen beforehand
00:26:33.240 and there's a few tools that we'll link to also that we've been using to help speed up tests there's a gem called
00:26:40.140 Spring that we've had good experiences with we didn't introduce it for the setup part
00:26:46.140 but look for it in the Ruby comp tutorial or rails comp tutorial website
00:26:53.460 so we have a failure here that says template error undefined local variable
00:26:58.500 or method post and it's failing again it's giving us
00:27:04.140 the stack Trace where things are failing it's in task line four
00:27:09.840 so if we go back to the previous file line four this is
00:27:15.120 where we're failing and we don't have a post method for this controller
00:27:20.159 so it feels like we should put the controller in is that right
00:27:26.039 uh you need to have bright post needs to be a
00:27:31.559 symbol over there other method type oh yeah thanks see mistakes are made
00:27:39.120 this is the joy of pairing is it things get spotted much faster
00:27:46.740 oh yeah because I left off the colon so it didn't route understand it as a
00:27:52.320 symbol great so we're missing a controller now let's make a controller
00:28:00.659 so I'm going to go app controllers uh what should we call this thing
00:28:07.919 so I wanted this one to be the completions controller yeah
00:28:18.000 so class completions controller application controller so it's going to
00:28:25.320 inherit let's give it a method create well wait a minute you're waiting
00:28:31.500 you're writing a lot of code here yep you're right jumping ahead
00:28:38.100 thanks for catching that one step at a time one step at a time so
00:28:43.919 our failure was we're missing the controller I add just the bear controller
00:28:49.200 and now we get an error here which says the create action could not be found for
00:28:54.360 this completions controller so the next step the thing I jumped
00:28:59.460 ahead to is to write the create method
00:29:05.700 so I think we'd probably want to do we probably want to find the task
00:29:14.220 probably even program available
00:29:19.740 and then we'd want to touch completed at and this task ID is available because
00:29:26.460 it's a nested resource now so the URL would look like tasks the ID of it and
00:29:31.620 then completions towards the end of the URL so this will make the task completed and
00:29:39.899 then we're going to redirect to the root path so we'll just redirect back to where we started
00:29:48.000 run our tests again
00:29:56.399 you get some hot SQL here active record statement invalid SQL Lite
00:30:03.299 3 SQL exception no such column completed at update to ask set updated at Etc so what
00:30:10.980 this tells me is that I have no completed at method in my database so I need to
00:30:17.760 create a migration to add that to the database
00:30:23.580 so I'm going to use the rails generator so it's rails generator
00:30:30.240 migration let's call this add completion date to tasks RB
00:30:40.500 I don't think I need the RV there yeah you're right
00:30:46.980 and it should be rails generate yes thanks
00:30:57.059 so the other nice thing about this now is it the tests are driving our
00:31:02.100 data structure too and so we're not kind of doing upfront design on fields that we think we're
00:31:08.039 going to need we're allowing the tests to actually have us add these fields to
00:31:13.140 the models too
00:31:26.880 so we're going to do is we're going to make the completed at column a timestamp
00:31:32.580 it's a little store the time in which we completed it does that look great looks good to me
00:31:39.240 okay so let's do rake DB migrate and then DB
00:31:46.020 test prepare I forget to do rakedb test repair so
00:31:51.240 often I created an alias to just that's just migrate and it does both of these together
00:31:56.700 those are separate databases your your development database and your test
00:32:02.220 database and this will migrate both
00:32:12.779 looks like it worked let's run our tests again
00:32:28.020 great so what we're failing to see here is some CSS
00:32:33.600 expect Paige to have csstdd completed or TD completed text task name so it's saying can't find
00:32:41.640 this within this with this text inside of it
00:32:46.799 so let's go back to the view
00:32:54.960 oh sorry the task
00:33:12.299 let's only put this it looks like we've got an extra TD in here now how about if we added the class
00:33:18.000 to the surrounding TD there yeah
00:33:23.159 good call so we'll definitely add this task class and then let's add another class if it's
00:33:30.779 completed how's that sound looks good so let's use a little Ruby Little Herb
00:33:37.500 make it completed if task completed at
00:33:45.720 hmm because I quote and close the tag
00:33:52.740 does that look right that looks good to me so when the
00:33:57.840 buttons clicked a post is sent to the completions controller completion controller looks up the task
00:34:04.100 es the completed ad which is a rails method that puts a timestamp at the
00:34:10.440 current time and then redirects back to the root path and now on the root path when this HTML is regenerated we should
00:34:17.639 have a completed class on this TD
00:34:23.339 we'll run our test again look at that our first green test there we go
00:34:36.659 so now it's time to take a look at some of the code we've written and see if we can make some
00:34:42.060 improvements so I'm doing a good dip
00:34:47.760 so that's going to do is show the changes that we've made
00:34:53.940 so here's our view looks pretty good
00:35:00.180 I don't think there's anything we can refactor here we're typically looking for areas of
00:35:05.580 duplication um especially naming it's so important that it's worth a
00:35:12.900 second read to make sure that all of our variable names make sense so think of routes look good
00:35:20.700 this is our schema you can see that it added this column to
00:35:26.040 our table right so this is my error that I fixed in the
00:35:33.480 documentation so we'll commit that here's our scenario
00:35:42.900 so I feel like this looks pretty good there's a part of me that thinks that these that have CSS selector might be
00:35:51.720 nice to hide that behind a method name to make Our intention there are
00:35:57.000 a little more obvious and hide some of the implementation of the view sure
00:36:04.440 let's go back to our spec features
00:36:09.839 right here so you're saying this have CSS PD completed that guy yeah I think the
00:36:16.020 the reader of the test doesn't need to know if there's a TD with completed so maybe we can put that under
00:36:22.320 a method of like have completed tasks or something of that nature
00:36:28.920 and then pass in the tasking yeah I like that
00:36:42.480 can I do this
00:36:50.700 what do you think of that yep I kind of feel the same way of the uh complete too
00:36:57.200 so we can now make this test start to read a little more english-like by Heidi in a way some of these capybara
00:37:03.839 steps here well let's make sure this guy passes first yes good call
00:37:10.200 so now's when I start to run the full test Suite just to make sure sorry the full test file to make sure that it's
00:37:16.560 all working especially when I start adding methods so that looks good actually I'm going to
00:37:22.980 commit this real quick in your feature branch which I see you
00:37:28.020 created oh no
00:37:33.900 so embarrassing live coding so our typical kind of development process here will be to create a
00:37:40.320 well-named feature Branch with the initials of the person coding
00:37:45.780 when we get to a point where we feel like our code's looking pretty good we'll push that future Branch up to GitHub create a pull request and then
00:37:53.760 put that pull request in the campfire where other teammates can jump in and add comments and hopefully give good
00:38:00.180 feedback on the code that we're trying to get into master
00:38:06.119 and passing tests to complete task
00:38:13.859 so normally what I would do is use bullets here in the commit message and put a lot more detail regarding what
00:38:20.579 this commit is we like to use our git commit history as a sort of
00:38:25.880 as the history of the application and here's where we usually will do it but for sake of time I'm just going to
00:38:32.460 leave it like this get push
00:38:38.820 and what autoresh is doing here is making a commit with the passing tests this is a pretty simple feature but on a
00:38:46.260 bigger feature where we might want to move around some code it's nice to have a point in time where everything was
00:38:52.020 green that we can reference in case something goes wrong during the refactoring phase
00:38:57.839 so it looks clean so you're saying that we try and refactor something else out of here yeah I feel like the uh the TD contains
00:39:04.980 the reader of the test might not care so much about the fact that it could be a TD or an LI
00:39:11.579 or whatnot so why don't we put that behind a well-named method also what do
00:39:16.980 you think for a name um I mean what's what's it doing we're completing a task right yeah so maybe we
00:39:22.680 could have a method called complete task and then pass it the task name
00:39:27.900 yeah that looks that sounds good so let's do that
00:39:46.320 oh so you'll actually want to grab that within uh yeah there too
00:39:56.579 how's that look that's you
00:40:01.859 yeah oh let's put a parameter on here since we're passing one down I feel
00:40:08.160 comfortable moving the click link down too so maybe just pull that whole block down
00:40:22.260 I mean you'll need the two end around there yeah there we go
00:40:28.800 let's run the test again so the method is complete task task name
00:40:33.900 so then yep that looks good so we've done there is we've extracted a method that
00:40:39.359 hides the implementation and reads a little bit more nicely so that's good like that
00:40:55.320 looks good so I'm going to commit this also
00:41:00.540 I think the one more thing I noticed was there when we're looking at the first code that was running for the add
00:41:07.140 task we repeated a bunch of that for the completion
00:41:13.740 so I feel like maybe it would be nice to extract that into a method that maybe both scenarios could use
00:41:18.960 yeah so what you're saying is this uh this whole setup here
00:41:26.220 right exactly okay so I'd probably keep the task name variable in there but maybe we could
00:41:32.579 create a method called create task and that would then Drive capybara to
00:41:39.660 create the task like that you got it
00:41:52.619 so we'll call this create task
00:41:59.280 name like that let's make sure we're still
00:42:05.339 passing now
00:42:16.380 Yep looks good great and then we should be able to uh reuse that method in the
00:42:21.660 first scenario which is adding a task
00:42:28.020 that would be that'll be create task though
00:42:33.780 so you have complete but that's going to be create yeah yeah sorry
00:42:44.820 yes that's exactly right
00:42:51.960 no totally um so we're gonna we'll talk about the model one in the next section but the thought here is that you want to
00:42:58.800 verify with an integration test that some steps happen and I think uh
00:43:04.500 verifying that creating a task um through the web browser works is great
00:43:09.599 and then the one thing we have to be careful with integration tests is they're a lot slower than unit tests so
00:43:15.960 being able to pre-populate some data into our database and then assert that it shows up on a page is a way for us to
00:43:22.619 do some setup in the system so right now we're kind of manually setting up in the other two but with the
00:43:29.160 uh was it view task we're kind of priming the database with some data and then
00:43:35.359 asserting values on The View to make sure that data exists
00:43:41.099 so this
00:43:52.680 state
00:43:58.740 so that's a that's a good question but we haven't changed any of the assertions though so if the assertions are still
00:44:05.400 running green we can typically feel pretty good that some of the setup steps haven't been broken because the the test
00:44:13.140 is still the assertion is still green on that test
00:44:29.040 okay
00:44:46.560 so that's interesting so so uh participant has worked at a company where they did some refactoring and
00:44:52.380 tests and they started getting false positives because some things have changed in the test Suite but the
00:44:57.900 assertions weren't kind of asserting on the right things now it's definitely something to watch out for uh we
00:45:03.480 typically do a lot of refactoring in our tests we treat it as part of a first citizen in our code base and
00:45:10.020 aggressively try to get rid of duplication with the hope that they become easier to read but I think it's
00:45:15.599 definitely I wouldn't do that in a in a feature that had nothing to do with that part of the test Suite like that could
00:45:21.180 be maybe its own refactoring in itself and then obviously have someone look at it to make sure that that what we're
00:45:27.119 asserting still makes sense there yeah I think that makes sense and two things that are important to mention one is
00:45:33.119 that tests are still code and you should treat it with all the same principles
00:45:38.760 that you would code so you should try and keep it dry and extract methods and trying to refactor it wherever possible
00:45:46.400 so that's really important and one of the things that you might catch
00:45:52.200 as your refactoring your tests is errors where you're removing assertions or changing them or basically
00:45:58.500 changing the intent of the test and you can catch that not just in pair programming but through
00:46:03.960 the code review process so that's a great place where if you're changing tests which again it's a great
00:46:09.839 point they're very valuable you don't want to remove their power the code review process and pair
00:46:16.560 programming really allow you to catch any errors along the way yeah I think we use the tests really to
00:46:23.280 kind of Drive the way we design the system and I think it's a little bit scary to say
00:46:29.220 that because your test Suite passes that you are totally confident that everything in your system is correct
00:46:34.380 because they're not going to catch every bug I mean so we still need to be active about um
00:46:40.020 as people testing the code that we're putting out there um to verify that expected behavior is
00:46:46.980 happening
00:46:52.740 okay all right
00:46:58.440 does that look great how do you feel this feels pretty good it feels like we've removed some duplication with this
00:47:04.200 create task method which is really nice um we're able to complete the task and
00:47:09.540 then have the completed task visible this reads a lot more nicely to
00:47:15.300 me so we're setting a task name let's create the task then let's complete the task and then we expect the
00:47:21.720 page to have the completed task so this goes back to that point about documentation when this
00:47:29.400 this test right here tells me exactly what feature the web application should have
00:47:38.760 so I like it I think these are good suggestions great so why don't we do a push up to GitHub now and we can do a
00:47:44.640 compare against master and give it a last set of eyes
00:47:50.819 so we created the completions controller gave it a create method
00:47:56.839 we updated the completed at timestamp then redirected to root that looks right
00:48:04.020 in the view we added a nice conditional class tag I think that was really really
00:48:11.400 nice um and then we have a link to complete I like that we extracted the completions
00:48:17.579 to a separate controller so we've encapsulated that logic elsewhere
00:48:25.740 that's great you may have some of you have used routes before you might not have seen
00:48:31.560 these but we like to restrict the available routes to only the ones that we use
00:48:40.140 keeps your routes file a lot cleaner right that's when you're doing rake routes later you don't have a bunch of noise in there of routes that may not
00:48:46.920 exist exactly that looks good we're migration is good
00:48:54.240 looks like it worked and I screwed up our slides so we'll fix
00:48:59.280 that and then we've extracted some methods
00:49:05.339 here added a new scenario
00:49:10.440 Yep looks good to me great so I'm going to squash this down yep
00:49:18.000 can you talk a little bit about what squashing is absolutely so so when we're working in a feature Branch quite often
00:49:23.640 we'll make either some work and progress commits or we have a commit for our first passing test we have another
00:49:29.520 commit for extracting a method um and this kind of muddies up our git log a little bit so as a whole we want
00:49:36.420 to have one nice git commit message for this entire feature so what autoch is
00:49:41.880 doing right now is called an Interactive rebase so he's taking all of the commits we've
00:49:47.160 made in this future branch and squashing them down into hopefully one very nicely named commit that will
00:49:55.980 have a good overview of what this code is adding to the code base and quite
00:50:01.560 often if we're using a tracking systems such as you know
00:50:06.960 pivotal or trajectory or Trello or jira will also add a link at the bottom of
00:50:12.660 this commit message here to the original feature request and that will give
00:50:18.060 future developers looking at our commit log another reference to where this code
00:50:23.160 came from what the intention was behind it so write a little note a couple lines
00:50:28.800 describing what that says commit that
00:50:33.900 I'm going to get pushed to the branch and it's going to complain because I've
00:50:39.060 changed the history in the branch so it's going to reject it
00:50:44.160 I'm going to get push Force this is something you should only do in
00:50:49.200 a feature Branch never get push Force to master
00:50:55.440 so if I look at the get log there it is
00:51:03.540 and now I'm going to merge this in looks good the one step we would have typically in
00:51:09.960 our regular workflow is doing the pull request on GitHub um we'll skip that step for now
00:51:19.460 I'm going to delete this branch
00:51:26.819 clean up after myself whoops delete Branch there I'm using a number of aliases I'm going
00:51:33.660 to try not to use them where possible if you want to look and see where they are they're in my DOT files and I'll
00:51:39.240 point you to those at the end and this just does a cleanup locally of deleting your local branch and then also
00:51:44.700 deleting your remote Branch to keep your repository tidy
00:51:51.599 so cool so that's our first acceptance test built in kind of a tdd fashion starting from the outside and then going
00:51:59.280 in as we needed to create new attributes on the task and kind of allowing
00:52:04.980 capybara to drive the way that we develop in an application yeah and one of the things as Harlow caught me
00:52:11.220 jumping ahead one of the things that's really critical is to really only focus on what that error message is and only
00:52:17.819 solve that one error message and let it proceed you through the process
00:52:23.040 and then you really have a voice telling you um what's the next piece of code you
00:52:28.859 need to add to your code base I find it now very hard to even write code without the tests telling me what to do it's
00:52:35.640 kind of like the whole once you start to get comfortable with tdd you really rely
00:52:40.859 on your tests a lot to tell you what your next decisions are adding code for a future
00:52:46.920 so that's that's one segment we have many more ahead but before we charge
00:52:52.619 ahead does anybody have questions on what we did any uh anything seem uh the
00:53:00.059 ordinary yeah let's have some questions