How I Learned to Stop Worrying and Love Unit Testing

Video thumbnail (Frame 0) Video thumbnail (Frame 9363) Video thumbnail (Frame 10137) Video thumbnail (Frame 10859) Video thumbnail (Frame 22493) Video thumbnail (Frame 34127) Video thumbnail (Frame 43121) Video thumbnail (Frame 44000)
Video in TIB AV-Portal: How I Learned to Stop Worrying and Love Unit Testing

Formal Metadata

How I Learned to Stop Worrying and Love Unit Testing
Title of Series
Number of Parts
CC Attribution - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this license.
Release Date

Content Metadata

Subject Area
We all know that testing is important. But it's also hard to get right. We'll talk about how to write effective tests that not only protect against defects in our code, but encourage us to write better quality code to begin with. You'll leave this talk with ideas on the philosophies that should inform your tests, and a good idea of what makes a good test suite.
Statistical hypothesis testing Trail Context awareness Functional (mathematics) Confidence interval Code Multiplication sign 1 (number) Control flow Continuous integration XML Mereology Code Computer programming Statistical hypothesis testing Power (physics) Product (business) Formal language Software bug Twitter Thomas Bayes Mathematics Goodness of fit Different (Kate Ryan album) Process (computing) Supremum Collaborationism Execution unit Software engineering Inheritance (object-oriented programming) Software developer Moment (mathematics) Projective plane Bit Unit testing Cartesian coordinate system Statistical hypothesis testing Product (business) Proof theory Word Uniform resource locator Process (computing) Software Complex system Quicksort Musical ensemble
Statistical hypothesis testing Wiki Causality Form (programming) Number
Statistical hypothesis testing Meta element Complex (psychology) Context awareness State of matter Code INTEGRAL Confidence interval Multiplication sign Execution unit Source code Function (mathematics) Mereology Disk read-and-write head Computer programming Thomas Bayes Mathematics Type theory Different (Kate Ryan album) Object (grammar) Single-precision floating-point format Funktionalintegral Physical system Social class Scripting language Counterexample File format Software developer Keyboard shortcut Bit Mereology Perturbation theory Unit testing Variable (mathematics) Flow separation Statistical hypothesis testing Type theory Software suite Order (biology) Different (Kate Ryan album) Quicksort Functional (mathematics) Physical system Writing Metre Point (geometry) Functional (mathematics) Game controller Real number Disintegration Electronic program guide Control flow Continuous integration Web browser Number Statistical hypothesis testing Revision control Workload Goodness of fit Object-oriented programming Code refactoring Module (mathematics) Execution unit Dependent and independent variables Multiplication Information Confidence interval Interactive television Counting Cartesian coordinate system Ruby on Rails Word Integrated development environment Software Personal digital assistant Logic Object (grammar)
Statistical hypothesis testing Suite (music) Constructor (object-oriented programming) Code INTEGRAL Decision theory Multiplication sign Execution unit Combinational logic Mereology Neuroinformatik Expected value Mathematics Different (Kate Ryan album) Single-precision floating-point format Modul <Datentyp> Software framework Error message Descriptive statistics Exception handling Physical system Social class Moment (mathematics) Electronic mailing list Bit Unit testing Statistical hypothesis testing Type theory Message passing Process (computing) output Right angle Whiteboard Writing Point (geometry) Slide rule Functional (mathematics) Overhead (computing) Branch (computer science) Online help Web browser Rule of inference Statistical hypothesis testing Number Product (business) Workload String (computer science) Operator (mathematics) Summierbarkeit Condition number Task (computing) Execution unit Dependent and independent variables Information Content (media) Database Cartesian coordinate system Number Logic Personal digital assistant String (computer science) Statement (computer science) Formal grammar Object (grammar) Exception handling
Statistical hypothesis testing NP-hard Suite (music) Context awareness Code State of matter Multiplication sign Decision theory Mereology Test-driven development Neuroinformatik Software bug Web 2.0 Fraction (mathematics) Mathematics Strategy game Computer configuration Different (Kate Ryan album) Negative number Software framework Physical system Covering space NP-hard File format Software developer Constructor (object-oriented programming) Moment (mathematics) Unit testing Statistical hypothesis testing Arithmetic mean Process (computing) Order (biology) System programming Boiling point Writing Resultant Row (database) Point (geometry) Ocean current Server (computing) Mobile app Software developer Branch (computer science) Rule of inference Number Statistical hypothesis testing Product (business) Twitter Goodness of fit Term (mathematics) String (computer science) Operator (mathematics) Data structure Analytic continuation Condition number Task (computing) Time zone Dependent and independent variables Validity (statistics) Timestamp System call Pointer (computer programming) Integrated development environment Personal digital assistant Interpreter (computing) Object (grammar) Computational number theory
Physicalism Coma Berenices Content (media)
the of the the of the the
the of the the the everyone and welcome to my
talk entitled how I learned to stop worrying and love unit testing I'm Valerie Willard Tree Moss and I am a software engineer at hand please where I helped build tools for your favorite podcasts you can find me in the hallway later or on Twitter my handlers Bowery codes for podcasts recommendations but right now I know where you talk a little bit about unit testing before we get into the talk I also want to take a moment to appreciate location here in the beautiful city of New Orleans and to borrow an Australian tradition called the acknowledgment of country which is something ever saw Alan do nation ruby to acknowledge the native people who 1st lived on this land I take time to acknowledge the talk tokamak and other tribes the traditional custodians of this land and I extend our respects to other indigenous people who were present thank you for taking the time to appreciate their contributions to this land in this culture with me and have for coming to attend this talk with get started I'm happy be kicking off the testing track I hope that this can teach you something if you're already doing testing and to give you an idea of where to start is not something that's new to you I choose chose this just of Kermit the Frog partly because I love permit abroad and it made me laugh but the other reason is that I love the carefree nature of German deprived I think that a lot of the power the testing gives us with confidence and good tests allow you to be confident that you won't accidently break something good test allow you to to verify that a change in your code is an actually changing the functionality of a program and good test late you worry and maybe they don't let you be as carefree as comment but I'm hoping that they can come closer so now stop right off the bat with 1 hour test even border in the 1st place some of you may be fairly new software and just know that testing is probably something that you should do without really knowing why I talked a little bit about confidence and 1 way you can think about test is also as an act of kindness when you write a test you're taking the time to verify that your code works this is a favor to your teammates and your future self think of it as an investment coming into a new code based or starting a new project often feels familiar in certain ways maybe it's the language you're familiar with or a kind of program that you've written before but there may be a little gaps or assumptions that you make that are incorrect and it's kind of like playing croquet with a flamingo and hedgehog there are ways in which things might seem familiar but there ways that they're really not at all what you expect You're old assumptions may not hold true and you have to figure out where the gaps are between your understanding and reality and testing can help you bridge that gap who are tests for so let's take a moment to talk about that there's a good story behind this quote my parents are both in the art world and got me this book written by a friend of theirs about being a professional artist I'm pretty sure they were hoping idea professional artists I'm not but I really love this book it's called art and fear because I think that it's incredibly relevant to programming in all sorts of creative work and I'm really obsessed with it this will not be the last time I put in this talk I have an idea for this talk or I just lecture about this book in the context of programming but that's for another day I had to sneak it and somehow so to all of you words about yourself what matters is the product of the finished artwork to you and you alone what matters is the process in the context of software in the process of creating our work is often a collaborative 1 so it's definitely a little bit different from being a solo artist unless you're just working on a side project by yourself that said writing test is part of the process of writing software not the finished product a user of your application doesn't care about your tests as long as the product works you should care about writing tests because they will help you build a product that works if you're a user you probably rather use the product that works perfectly and has no test but is a software developer it you'd much rather use the product that has some issues but as well test so the 1st and perhaps most obvious function of tests is protecting against bugs or at least catching those bugs before they make their way of production the software that you're working on is likely to be a very complex system you're probably not going to be the only 1 modifying it and it's not going to be possible to keep track or understand what's going on in every part of the application at any given time a test therefore conserving as an audit trail of how something is supposed to work or used to work when a test fails you should have some proof or paper trail of when that test used to work so that you have an easier time identifying what broken you can use test to prove that your code does what it says it does when you write ideally you can use a continuous integration process that will test your code every time you make a new command that way when you're tests is green ones 1 commit and write the next committe you can be pretty confident that some code that you change in between those 2 commits has broken it good tests coupled with continuous integration will allow you to pinpoint and quickly correct any of the breaks this test another great
asset the test can provide for use documentation you may be more familiar with
writing documentation in the form of comments or internal wikis but that can get out of date very quickly and cause use in trouble for example here I have right method that always returns the number for N I have written a comic talking about men at that only returns the number 4 but say a change of like this so now it returns
the number 5 but there is nothing that is going to force me to know update that common to make it reflect the actual state of a code base and if I return the change return value of the method the common remains there as this terrible blatant lies if you're using continuous integration test that have to be updated when they fail so they're more likely to reflect the current
state of the code base than your comments take it as a counterexample this test that I've written for the same method that always returns the number 4 in the above example nothing forces the common to be updated when the output of the function is actually switch to 5 and in a less trivial case this could lead to comments giving future developers including yourself misleading information about the actual state of your code another good 1 is the comment that say talk to so-and-so before you change this and so on so hasn't worked for the company for 6 months and good test can serve as an introduction to your code well written tests along with well main functions and variables should explain the desired behavior of your code as well as testing its functionality I can also help prompts you when your code is getting too complex and help encourage good practices I standing that said in practical object oriented design in ruby tests are the canary in the coalmine when the design is bad testing is hot writing tests as you write your code will help give you an idea of where the complexities in your code or if you're not sure how to test a method that method might be too complex and you need to be broken up into smaller functionality if you find yourself having to write lots of scaffolding in order to even run your tests I can help the signal that you may have too many external dependencies the logged a meter in object-oriented programming states that each unit should only have limited knowledge of other units and that a unit should only talked to its immediate friends so unit testing is a great way to sort of enforced that methodology how much is your class actually need from its neighboring classes and it's too much then writing unit tests will be more complicated which should serve as a hint to you to go back and simplify the code that your test another thing that SCO is allow for confidence and refactor if you've got some code that's written in a way that makes it very difficult to reason about you can rewrite it if you can reason about in the 1st place how are you going to preserve all that functionality without knowing quite what all that functionality it's without has it's impossible make changes to your code and ensure that you haven't broken other things you are indeed living very dangerously because you're only conception of how your code is supposed to work is within your own head and you have no way of verifying that this actually lines up with how it actually works for how it was originally intended to work which could be 3 completely separate that's efficient refactoring is only possible with a well written tests we this is an example of how taking the time to write good tests will take you to save you time in the future refactoring is a hugely important part of writing good code just as revision is an important part of writing I remember in high school when you were writing an essay and you would type in 7 type until you reach the word count and then you would print it out and never look at it again that's not the way that you wanna write code and you're not only depriving yourself of the chance Intraspect a bit more about the code you've written while it's fresh in your mind you're depriving future development in the developers of more insight into how your code is supposed to work and how to tell if it is working this knowledge is essential to making changes later Here's on fear again this could struck me in the context of testing because I feel like it's also kind of about refactoring you make good work by among other things making lots of work that isn't very good and gradually weeding out the parts that are dead I think this is absolutely true about programming as well as I do most of my work by just putting my fingers to the keyboard and reasoning out the problem at hand in whatever way 1st come since this is often pretty repetitive and sometimes needlessly complicated but this rough draft and starting point is essential to growth being able to edit it and make improvements to your code over time is an essential part of improving as about but you can't remove the craft without understanding exactly how your code is supposed to work and crucially when it stops working that's the insight testing gives you when you write tests that gives you a chance to look through your code to get a sense of how you feel about it the variables while named is a logic clear do you feel like you're doing something happy do that shocked and make changes where you see that after all you got some test now so that shouldn't feel quite as scary so this is things that test can do for you but what exactly makes a good test obviously not all tests are we created equal what differentiates them a good test we really only has to do 2 things it needs to break when code that you change has broken your app and not break the rest of the time these things turn out to be much easier said than done as it turns out is very difficult to predict what parts of an application are most likely to break with future changes in my tests in a way that exposes those things is also quite easy to write test that break in ways that don't actually indicate failures in your code like a copy change were a timeout because something takes too long or the changing formatting and output you should also be wary of tests that might be prone to timeout were seen anything that could change such as say the year or anything that about the environment that it's being run and so this talk is about unit testing but we haven't really differentiated the different types of tests and what they really mean you'll hear at slightly different definitions from different sources these are the definitions that are used in the Ruby on Rails guides there are unit the functional integration and system test a unit test test the smallest functional unit of code they can such as a single method on a single class in integration test test aspects of a particular workload and thus has multiple modules in units of your software what's you might create an integration test to make sure that users can log on or create accounts functional tests look at controller logic and interactions they're testing that your application handles in response to a request correctly this says for example tests on your controllers in a real sense system test allowed test user interactions with your application running tests and the real or headless browser again and the case of rails system tests are like an automated QA scripts and probably most closely mirror the way you would perform manual QA in an automated environment so out of all these types of test I'm choosing to focus on unit tests so why is that of the test types I talked about you'll notice that unit has survive are the simplest
I like them because they're easier right easy to run easy reason about and also help encourage modularity and cleanliness in your code as we discussed earlier individual methods are probably the things in your code that you have the best understanding of making them easiest to write good tests for and if your code is clean and modular well-tested units should lead to a functional application unit tests are also very fast run since they have the fewest dependencies and don't require spinning up something like a headless browser that said there will be times when you have to write other types of tests they usually thoughtful about when those times because of the overhead involved it's probably a good idea to have integration test for the most critical workloads of Iraq for example or in the case of a company that things that would be most likely to lose you a lot of money quickly if they were broken and shift to production system tests can be used to test important workflows but can be slow and brittle so should be used with caution to supplement a robust unit tests here's some of the things that you might be interested in testing this is by no means an exhaustive lists and there's plenty of documentation to be found online as to how to test different things these some of the things that I find myself testing for most often the most important thing to keep in mind as you start testing is to keep things simple each test should look at only 1 very small thing each of the bullet points I've listed here and the most common 1 at least for me I give an example for there are examples of what are called assertions you're establishing my idea of what your code should do and when you run the task to the computer will tell you if it actually does or not I add in an example of using spec to run a few tests in just a simple idea of the council and it may be a little too small to read but these slides will be online if you wanna take a look it's basically a I I'm saying expects 2 plus 2 equals 4 that returns true I then expect 2 plus 2 equal 5 and I get an error but expectation not met expected 5 got 4 so that's kind of the syntax that you'll be looking at and so the 1st time I run untested passes and when the test fails the failure message includes the expectation that was not met the expected value and the actual value it's important as you 1st start testing to make sure that you clean as much information as you can from these error messages because they can tell you a lot don't just say my test failed to go back to the drawing board really take a moment to think about what it's trying to sell you but you can see you are at for example you can test the exact value of a return value incidentally you can also use are a matching greater than less than includes the whole deal you make sure that a method causes and another method to be called you can check that a job is an cued you can check that idiot database object is created or destroyed you can see if something is true the a false or whether running a particular bit of code there is an exception and the content of that exception this is as I mentioned non-exhaustive list but instead meant to get you thinking about how you might start writing tested so what is the unit test as we noted a unit has looks to the smallest possible unit of code in the case of Ruby that's a single method on a single class in unit testing a method you should think about all the reasonable inputs to that function as well as how the method should respond invalid inputs your method uses branching or conditional logic you should have a unit test that he hits each possible branch or combination of branches here is an example of how I might approach unit testing this method that I wrote concrete it's a fairly trivial method it takes someone's name and says low-demand if it gets a weird input like anything that's not a string it just as a low and mentions that it in catch the person's name that's a design decision on my part I could also throw an exception or just called to strain on any input that I received the code examples here use spec but the general ideas should be applicable to whatever testing framework you're using because I have 2 possible conditions in my return values as I mentioned I wanna at the very least test every branch of any conditional logic that I'm using so I know that I need at least 2 unit tests if I wanted to be especially thorough I might tests for other edge cases like different types of non string input you can see how if you have lots of branching logic that this can multiply and get complicated very very quickly so let that serve as yet another incentive not to nest too many conditions in a single math I've written a simple test for each of the possible conditions in this case I written to unit has 1 that calls the method using the expected input this is something you might see Caller happy path I call the method using my name and it says Hi Valerie and then I call the method using using a number to you and I make sure that I get the response saying hired in capturing and just as the syntactical note here as apologize for having to use the ternary operator here I it so I could that everything on the slide if folks are not familiar with that syntax basic idea is that it's just an if else statements with the if part behind the question mark and the return value for the their right after that and then the return value for the else condition after the call and so the this item better specs has tons of resources on Be Testing best practices and also we use to write your test and down to like the grammar of how they should be written in order so that the print out of like the what failed and passed in your test suite is easiest for you to read and the same principles of readability that apply to your code are probably even more important in your past my general rule is that in English speaker who doesn't know Ruby should be able to read your test and have an idea of what it's doing in a stack things on named very deliberately to allow for that's and you'll notice that the test syntax is its and then a string do and in the string you can give an English description for what you're actually testing for and then the syntax here expects this thing to equal this thing should be fairly easy to parse the less readable your code is the more straightforward your test should be although although both should ideally be as straightforward as possible so
we've talked about what's good about half and why you should write them we've probably all been in or will be in situations where testing test writing is skipped or overlooked so why is that what makes testing hard work causes it to be passed over a lot of the challenges around testing boil down to time developer time computational time the passage of time writing test take time the 1st time you're writing something you're probably testing all your code manually in a development environment you've convince yourself pretty well that it worked and it doesn't seem like it's worth it to write test that why right automated tests that takes time that you to be spending writing your next feature test also take time to run and if you've continued it configured of continuous deployment environment where your tests have to all past before you can deploy to production this in 1 way is very deliberately slowing down your deployed process this can make it more frustrating to push say urgent urgent fix through specially if those tests take long a long time to run or have various failures you can also mitigate this by writing fast tasks such as unit tests as we talked about I keeping those tests simple and using tools like Zuse to help load your tests testing anything that involves time can also be challenging let's say you want to check that a timestamp is correctly recorded fractions of a 2nd elapsed between the time the object is saved and the test of around so the matching test actually fails what if the test server is on a different time zone then your development and production environments these issues can be mitigated by using gems like time cop which allow you to freeze time in your test environment and the final time aspect of time that can be difficult is knowing at what point in the process to write your test and if you're waiting to write down until the end or trying to write them long after writing the code under test it can be hard to remember what exactly you were doing and what things are most important to test we tend to overestimate our own abilities to remember things and you're likely to forget the context for your code and decisions very soon after writing I think we've probably all experienced the moment of coming to a piece of code that we wrote maybe 6 months ago and not remembering anything about it for the state of mind that we were in when we wrote it and even if you're not using true test-driven development you should be writing tests alongside your code and writing out an idea of what you take 1 year tests to look like before you begin writing code can be a helpful exercise in thinking about how you wanna structure your code another at really challenging part of testing if you're faced with an app or Kobe's with no test is trying to figure out where you can start testing instead of trying to take on the monumental task of writing tons of tests at once instead make sure that every new piece of code that you add as well tested you can choose a testing framework and use tools to get an idea of your test coverage and then you can just start chipping away at it I like to think about the Boy Scout rule where you leave your campsite clean and then you found it when you got there I am and leave the code cleaner and better tested then you found it with every pull requests you fixing a bug style before you fix it right it has that exposes it infants now go and fix the code turn green are you writing a method to make sure that you have a test a separate us for every branch of its conditionals think about edge cases as we were talking about but say method gets passed a nil value a string and 7 number a negative number 0 really big number think about the way it is you want that method to respond in those conditions and write tests that validate that behavior task over comments as a means of explaining a code of future engineers get everyone on your seem to agree that testing is important and and agree on a strategy you can use tools like cover also to give you feedback about what code is and isn't covered by the existing test suite once you have a starting point you can set a ball for example to increase code coverage by 5 per cent you can also decide for example that all hr need to be need to include tests in order the march now another thing that's really hard task is external systems are dependencies let's say that your code makes a call to an external API and then forces that response it's inefficient and clunky to actually make that call every time you run your test so what can you do you have a few options you can mark out a valid response new tests and just make sure that you during the correct operations on it you can use the tool like web mark to construct Baker http responses or a tool like these to make a real request once and they were the result performing all future test from the recording keep in mind that both of these methods rely on the current state or your interpretation of the current state of API response format and if that change is it has the potential to break your alive out but not your tests and with
that I hope they this talk is giving you some ideas for how to start testing if you haven't already and his giving you some ideas and things to think about in terms of your tests we is that something you're doing already FIL free define me later or on Twitter with any questions and if you're interested in working for my company where hiring and I'd be happy to chat about that as well and go forth and conquer that
this happened physics