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