 reasonable bit of technical stuff for a bit later and either this will speak to you from the point of view of reinforcing a perspective that perhaps testing unit testing in particular is something that you want to motivate yourself to do where it reinforces the fact you are already doing it perhaps it will answer a couple of questions that are unclear a couple of doubts in your mind it may also provide you with a couple of insights in terms of history technique and points to make to other people people are often find themselves in discussions technical discussions about practices where they find themselves trying to explain to somebody else who's coming from a very different perspective why this stuff might make sense so hopefully I'll hit at least a few of those points so I'm Kevlin Henney and I've got a stalking address and a spamming address there I've written some books and these relevant yeah the one on the right is relevant 97 things every programmer should know this is a crowd source and open source but very interesting things when they put out a call for submissions I got a I got a ridiculous number on testing there's a very high proportion of submissions on testing I couldn't take them all but it it was it was interesting how that came out I'll refer to one or two of them a little bit later now this is a this is an interesting tweet I got from Kirk Papadine yeah he was one of the contributors to 97 things Kirk is a Java performance specialist Canadian living in Hungary and he made an observation one day he tweeted this one at me functionality is an asset code is a liability now I found this absolutely fascinating and provocative because I spent a better part of my career convincing people that code is actually an asset but he's right he's dead right because what people want is the functionality the code is somewhat annoying the fact that there has to be code but what he's saying is code is the liability which means not that you don't care about it but you care about it very much because if it's a liability you want less of it you don't want loads of rubbish lying around you don't want technical debt messing up because the more of this you have the more likely it is that you will not be able to deliver on the functionality so there's this wonderfully counterintuitive result that because code is a liability you really care about it a very great deal which kind of chimes with what I have been trying to put forward which is the idea if you really do have to care about the code at some level or another but this idea is that many systems you look and it's the code that is the liability what people are buying is functionality and then eventually what they're buying is slow delivery and eventually there they're taking taking out government bonds in your technical debt they want the functionality but the code is the thing that gets in the way now testing is not the only game in town but there are a number of things that are going to help us I do also think it's worth thinking about the observation code is a liability we need to understand our code bug report this is actually the Norwegian for bug report I was giving a talk in a series of talks in Norway and I saw this and I said does this say what I think it says because the great thing is in English bug rapport means kind of understanding your bugs being at one with your bugs having a communication with your bugs like this this is PowerPoint about to lose my work what is fascinating about bugs is that certain classes of bugs at the level of a software product reveal a great deal about the internal structure they also reveal not just the internal structure of a product they reveal questions of architecture and practice and organizational technique let's let's look at this one first thing that's most obvious Microsoft Visual C++ runtime library so PowerPoint is compiled using Microsoft Visual C++ in other words Microsoft eat their own dog food which I've never been fond of as a phrase it's something of an American phrase I believe the Swiss talk about eating their own chocolate which I think I'm more in favor of okay but this idea they actually use their own compilers on their own products this is not what they used to do in the 1990s they use different compilers and it's a very interesting feedback cycle that when they started using their own compilers on their own products their compilers got better yeah because you have you have the operating system guys and and the applications guys going this isn't as good as what com you know you guys really need to tighten this up so the first thing is we discover it is written in C++ it is written it is compiled using Microsoft's C++ compiler then the next thing we might notice is it's a pure virtual function call this is curious pure virtual function call is an abstract method being invoked how do you invoke a pure abstract method how can that be possible there are one or two cases where it is possible it means you've either you've either you're either not running a static analysis tool or you've got a memory trampling bug now I don't know which one of these it is but I now have a question I can now go into the code base and say well okay what are we missing could we have caught this at compile time is a case of turning up the warning levels higher or running a separate static analysis tool or is this a runtime error in the sense of a memory error either way I'm learning something about the development practices either these guys need to work with higher warning levels or they need to take a little more care over the encapsulation of memory management however I think the most revealing thing here is let's just be clear what is the application that is crashing PowerPoint and where is the failure being reported internet Explorer oh I don't remember running internet Explorer I you know internet Explorer is the browser I used to download Chrome yeah so what's going on here what we're learning here is that the rendering engine that is being used typically for panels down left rendering engine used is part of internet Explorer and although Microsoft talk the component talk they don't walk the component walk in other words if I want to have that rendering engine I have to have the whole of internet Explorer whatever happened componentization where's my little rendering component dot dll yeah in other words which also explains the memory footprint to PowerPoint so this is an interesting thing here in failure a software system reveals itself it loses its encapsulation it shows you as it breaks apart not only the parts but also raises questions about the practices I've got a collection of these things people send me them now it's got to the point people all now actually send me these I retweet them on my Twitter stream I love this one Ikea so there we have hmm yeah Java dot line dot string plus the hash code did you find what you were looking for no I don't think so so now I know that Ikea use Java for this I also know that this particular printer product uses see assertion failed okay so for C programmers it's not too bad I mean they've kind of not they've actually used vowels a lot of C programmers don't believe that vowels exist and they ripped them out of their names but it fell at line 702 that's not massive I've seen longer but that doesn't make me feel too good that's I think that's a little bit long you know I saw I'm learning something about the product I I've got a whole collection of these I'll be using them in subsequent talks so there is that there is an observation here that comes from Andy Hunt and Dave Thomas in pragmatic programmer it's lovely little mantra test early test often test automatically if it's such a good idea why do it last if it's such a good idea why do it just once but if you're gonna do it a lot you might want to you might want to take take some time to automate it now there's some there's very interesting thing I still find this I find this with some agile teams as well that there will be a little there's a little betrayal of what people actually mean what they're thinking they will say things like yep we're agile and then they will accidentally slip in oh yeah yeah and then there's the testing phase that's interesting and so in a traditional sequential development life cycle like the waterfall where does testing come where is it right yeah right after development in fact actually that betrays a very interesting perspective I'm gonna come back to that one it's right at the end isn't it let's forget all about software development for a moment let's just think we are making a thing if I put the testing phase right at the end right at the end in other words the next thing is this goes out the door what am I expecting when I go into the testing phase it's working yeah otherwise I wouldn't put it at the end now this is a this is a big surprise to a lot of people because they never think of it like this and I was one of these things that if I knew nothing about software development culture anything like that if I took a step back and said are you're creating a thing you're creating an artifact and the last thing you do is test you must be expecting it to work because otherwise it wouldn't be the last thing you did there is nothing after that so this is very interesting idea that it's a separated thing but logically if you put it at the end you are expecting it to work now sometimes when I ask that question and then interestingly enough I get this from both developers and managers they'll say oh we're expecting it not to work and I said well if you were expecting it not to work why did you leave it so late if you're expecting it not to work you'd have you'd have got down to it and sort it out earlier and then one of the other key questions that I ask is what actually dominates such a testing phase in software development now we use this word testing testing has a very honorable feel to it it's a very positive thing but what actually goes on in a testing phase at the end of a life cycle what is that one of the dominant activities I'm going to give you a clue it's not testing what are we spending a lot of time doing fixing now imagine if you submitted a plan given that this this lives in a plan driven world you submitted a plan and you said to your you said to your your uppers you know there you go it's going to be here's the testing and fixing phase or the fixing phase let's just call it the fixing phase it's people would feel a little awkward about that it doesn't sound quite so good we're gonna we're gonna make we're gonna create something broken and then we're gonna try and fix it and if the wind is in the right direction and luck is on our side it'll be out the door all working fixed so why are you good so the question has to be why are you gonna create it broken now there is another challenge here this goes back to this common mental model that testing is somehow separate from development in other words here is development and then here is testing we I live in Bristol in the UK Bristol one of these we have in Bristol is Airbus one of the one of the one it's one of the major Airbus sites and I can't remember which bit of the Airbus a380 they built I can't remember it's the wings I think it's the wings but I'm fairly sure that one of the things they don't do by the time they actually attach the wings on to the fuselage they don't sort of sit there and go well it should probably work by the time they reach that point they have an immensely high level of confidence this stuff works and these are this is the largest wingspan of any commercial craft it's about 79 meters tip-to-tip and it's only attached to the fuselage by about 30 centimeter overlap by the time they get there they're not sitting they go where we think it kind of works they have every reason to believe that it will work and the reason they do this because it turns out that even in industrial processes where there is a test phase at the end it's not the only test phase it's the last one they have every reason to believe it works because what they've been doing during development is testing and I was this is our final check it before it goes out the door thing but we've got to that point we are absolutely sure that it works so this kind of informs a very different perspective the idea is that it may be that customers want another check of something that may be that there is a reason particularly with cross-disciplinary work where you're dealing with a hardware and software it may be there is a reason that you want to do something at the end just to do this reality check before it goes out the door of course if you do a more frequent deployment then you're going to try and make that more automatic but the idea is in either case you want to have every confidence that you know what the answer is going to be it should be a failure as a surprise and an exception and not the norm now given that there is this interesting question what is it that developers think they do so what do programmers believe they do the reason I asked this is because one of the most common objections to spending more time unit testing is it's going to take me more time yes this is going to slow me down it's going to take me more time this is all to do with this this all comes out of a curious belief that what programmers believe they do is write code there is this idea people have this idea this fantasy in their head I write code for a living oh and then there might be other stuff but I write code for a living writing code is what I do if you get me to write anything else if I'm writing these tests I'm writing less code by definition when you actually look at what programmers do they spend most of the time reading code debugging it searching the web going to meetings discussing things wrestling with the build system drinking tea coffee or whatever caffeinated drink drives them to that through their code they copy and paste an awful lot based on my experience and somewhere somewhere down there they write code there is this mental image this idea that you have of yourself the self-image I write code and then there's other stuff no there's other stuff and then if you're really lucky you might write some code or there's another way of looking at it all this other stuff is writing code that is what you do that's what takes now I had this wonderful insight I was running a training course that now a bank in London and I got into the I got into the lift anything what day was this Wednesday one developer talking to another I really hope I get to write some code today yeah me too you know Monday was just like all meetings and stuff like that yesterday I was firefighting and doing stuff like that and so far you know today is looking like it might you know he'd been in since six o'clock you know it's I think I might get some code done today it turns out writing code is almost anomalously rare so the idea that writing tests is somehow going to reduce the amount of code written is first of all a little bit of a fantasy it's based on an ideal view of your own self-perception and we are very bad when it comes to perceiving ourselves your own mental image of yourself is probably ten years younger and a lot more attractive yeah am I right yes I think so yeah and the same for your code and the amount of time you spend coding your code is pristine and awesome if only you didn't have to work on that legacy code base then all of your programming goodness will be unleashed upon the world it'd be fantastic if only you could spend more time coding sadly that's not really what goes on so here's what here's a sort of a slightly different agenda read code test search the web like code drink tea coffee etc it turns out that when we actually look and this this applies for test driven test after when people write tests something very interesting happens they write less code it's true they do which is obviously not what some people want to hear yes all the studies demonstrate people write less code they write less code to do the same functionality they write less code with fewer bugs in other words functionality is the asset code is the liability you reduce your liability so it's an interesting perspective now whenever I present this one of the inevitable things that happens it's somebody says if I if I've got a manager in the room there's normally a case well what can we do to supervise this or control it there's a fear that people will spend their whole time testing now I have heard of a couple of projects where that has happened but it's such a luxury to have I mean if that's a that's a problem you want to have you know it's so sometimes people say well what happens if my developers start writing just tests all the time and there's loads and loads of tests I said tell you what get back to me when you have that problem if you have that problem you will be you know that's a luxury to have but it's so rare so there's no sense I should control this so my answer is what should they do to constrain these activities and control them and supervise them nothing it should be treated as a development practice a standard development practice like compiling I don't I don't see that other people get involved in the compilation act you know people wandering around going like well how many times you compile today I think you're using up your compilation quota yeah you can compile anytime you want so here's some motivation clean code that works on Jeffrey's pithy phrase this is quoting from Kent Beck's test-driven development by example which is now 10 years old it's the goal of TDD clean code that works is a worthwhile goal for a whole bunch of reasons it is a predictable way to develop you know when you're finished without having to worry about a long bug trial it's not perfectly predictable if things were perfectly predictable I suspect that the world be a very different place but there is a certain level of confidence that comes with that in other words there's you're reducing the element of surprise gives you a chance to learn all the lessons the code has to teach you this is something else that we need to consider code code is an expression of knowledge when people talk about software developers as knowledge workers they kind of forget that there's a real sign to this it means you have to know stuff you have to learn stuff you have to learn not simply programming languages and libraries you have to learn about the domain you have to learn about the architecture how am I expressing this is this the best way to do this you know and the observation if you're only slapped together the first thing you think of you never have time to think of a second better thing there's another interesting thing if you're writing code to test your code you have your you have a very privileged perspective you're the first person to use that code what does that feel like is it feel convenient is it easy is it difficult is it awkward this is a really subtle point because a lot of people think that the goal of testing is merely to find bugs I started the talk considering bugs but turns out that's not really the whole thing I also consider the fact that code is a liability it's not just the bugs I mentioned technical debt and other issues there is this idea that part of the goal of testing is not simply quantitative feedback you have five test failures that's quantitative there is a qualitative feedback the very act of writing a test gives you a little bit of feedback on level of awkwardness in the code it's it's one of the kind of first points where you get some feedback I think there's a lovely example did a code review with a company a few years ago and lovely example of a method that had five Boolean arguments if you're inside the method it actually looks okay because they're all it's all very well-named you know you've got one Boolean argument named is enabled another Boolean argument is active and stuff like that when you read the method it's actually quite readable if is enabled then do something if is active then do something it looks very readable on the outside though what does this method look like when you call it true true false false true true false false true false how readable is that it's when you start when you use your own code when you eat your own dog food so to speak when you are actually trying it out you kind of get a little feedback is like well you know what that's not so smart that doesn't look so clean you're forced into this point of observation and I've certainly in the past thrown away a number of tentative designs simply by writing tests for them this is really awkward this is difficult to use you know what if I think it's difficult to use and this is my baby what are the other guys going to think so there's a key observation there it improves the lives of the users of your software there's a sociological aspect here as well people other people let's your teammates count on you and you on them it also feels quite good to write it when you get into the swing of writing tests there is a certain satisfaction that comes from doing that so there's another thing that we want to be careful of here term TDD has suffered some kind of semantic drift over time and a little bit of semantic delusion delusion as to Coburn know this observation very many people say TDD when they really mean I have good unit tests I have guts I like this term guts this is good Ron Jeffries one of the original XP is also mentioned in the previous slide trying for years to explain what this was but we never got a catchphrase for it and now TDD has been watered down to mean guts in other words sometimes a team or an individual will claim to be doing test driven development and whilst it's certainly true that they are doing unit testing they may not strictly be doing TDD and whilst they're producing good unit tests again it may not strictly be TDD it's worth keeping in mind that TDD is a very specific class of practices but the objective good unit tests it turns out there's many ways to arrive at good unit tests now what about the history of TDD most people's site Kent Beck and extreme programming this is the this is where TDD took off test first programming idea this is where it became popularized and exercised and practiced in other words this is where it matured and primarily in the Java world subsequent to that is where if you like TDD grew up it's where it moved out of childhood into adolescence and into maturity but actually it turns out that TDD has a much longer prehistory but it just simply wasn't advocated or referred to as a distinct practice in its own right I came across this interview a few years ago with Alfred Aho Alfred Aho is known for his compiler work data structures and algorithms work and he's the A in orc Aho Weinberger Kernighan lovely little language if you've never worked with it and in this interview now ask would you do anything differently in the development of orc looking back he responds one of the things I would have done differently is instituting rigorous testing as we started to develop the language we initially created all because a throwaway language yeah that's never happened in software before you know it's sort of here's a patch it's only it's it's only a stop gap we'll do it right for the next release and that becomes your next release so we didn't do rigorous quality controls part of our initial implementation now I mentioned to you earlier that there was a person who wrote a CAD system in orc now I'm just going to pause there as anybody used orc right what's the longest script you've ever written 50 lines yeah and you know I'm a big advocate of the language I might have hit 100 lines to write a CAD system you have to be you it's kind of your it's one of those things you'd be slightly impressed but also slightly concerned you know it's just like wow you did that so the reason he initially came to see me was to report a bug in the orc compiler he was very testy with me saying I had wasted three weeks of his life now when somebody walks into you and they've been mad enough walks into your office and they've been mad enough to write a whole CAD system in orc and then they say you wasted three weeks of my life you pay attention so I held up Brian kerning it after this we agree we really needed to do something differently in terms of quality control so we instituted a rigorous regression test for all the features walk any of the three of us a home one burger Kerninger who put in a new feature into the language from then on first had to write a test for the new feature there you go TDD 1970s it turns out it does have a long prehistory it's another example here that relates to it Alan Perlis recipient of the first cheering award of our member currently I'd like to read three sentences to close this issue a software system can best be designed if the testing is interlaced with the designing instead of used after the design okay simulation which matches the requirements contains the control which organizes the design of the system that's not immediately obvious what that is but Glenn Vanderberg pointed this one out to me that that's mock objects through successive repetitions of this process of interlaced testing and design the model ultimately becomes the software system itself the key of this approach has been suggested there's no such question as testing things after the fact etc etc etc 1968 the original software engineering conference apparently back in 1968 they had a clue what software engineering was but in 1969 it all went downhill I spoke to somebody a couple of years ago and she was describing a the work she used to do in the 1980s for particular company and she was describing test first development it was a test first programming it was absolutely fascinating and the reason that she did it was because of a lack of confidence she was all her colleagues seemed so very very confident of their code and just was just as one of those clues in life confidence doesn't mean you're right but human beings we like confidence in others and we think that they're right when they're confident it's it's deep in our wiring and so her colleagues seem to be very very confident about their code she felt more reticent about this and as a result she adopted a test first approach because she was never so sure that her code was going to work so what she'd do is she'd write some tests she write little test first she'd write some code make sure that that worked write another test write some code just make in other words her confidence derived from a more empirical approach but she didn't tell any of her colleagues this because she thought it felt stupid yeah well actually it turns out it's quite a good idea for exactly the reasons that she described now observation from that price and Steve Freeman everybody knows TDD stands for test driven development that's actually not true I did have a conversation with a very very smart developer five years ago when I mentioned TDD and he said what top-down design so that's not necessarily true however people too often concentrate on the words test and development and don't consider what the word driven really implies for test to drive development they must do more than just test the code performs its required functionality they must clearly express that required functionality to the reader now this is a interesting this is the blurb from a conference session that Nat and Steve did an XP day in London in 2007 they and this is a very interesting session sadly I couldn't go to it I love the blurb but they did something else in the session what they did is they got people to implement simple toy problems in pairs they handed out simple problem descriptions on index cards people in pairs would solve it write code and tests write code and tests and there were different problems being solved in the room once you had written your code and tests you passed your tests to another pair without the card and without the code and now what they had to do is implement code that satisfied the tests now I know I've sort of written when I think of some of the tests that I've written I'm absolutely well yeah I would not be happy with this because although I tested that the code kind of did what it was supposed to I did not make very clear in the tests what the code was supposed to do it's quite a challenge could I actually hand off my test to somebody else and have that treated as a specification now this is an interesting point because when many people sort of respond to the question you know why are you testing your code what reasons why I have to test my code people often respond along the lines of to test that it is correct to test that it does the right thing to test that it works but it turns out that that's not actually a good response because that only pushes the problem one step back the question is what do you mean by it works what do you mean by it is correct it turns out understanding what on earth it is you're trying to do is far harder sometimes than actually testing it expressing the intent of the code they must be clear specifications of the required functionality um now sometimes people will say well immediately that I need a particular testing framework to do this with and so no no no this is really to do with the sensibility of how you test so um let's yeah let me let me just take a minor detour from the uh minor detour from the slides um and let's see we've got uh that's that's up there like that that's good um what I'd like to do is just explore a very simple example and the way that most people would go about testing it um sadly I don't have any cups so I'm just going to steal a glass here thank you very much right well we'll just call that a cup for the sake of argument and we are going to develop a cup class how hard could that be and if we start out in this kind of way many programs will sketch it that will do that and well I guess we'll have some kind of constructor and I guess we'd like to know uh if it's empty or not and I guess we would like to be able to fill it that makes a certain amount of sense I guess we'd also like to be able to drink from it and somewhere in there there'll be some private implementation and I guess it's probably going to be other methods as well so how are we going to go about testing this okay so the way that a lot of people will do this and indeed not just people this is the fascinating thing is it's not just um it's not just people that do this uh it's also uh automated tools so the way a lot of people go about this is to write something like cup tests cup test and then they will do something that is obvious and intuitive and really wrong and eclipse does this for you in fact many environments will do this for you this is the great thing about code generation it allows you to generate the wrong thing faster yeah so a lot of a lot most code generation out there is just not worth the paper it isn't printed on it's just shockingly bad we're going to do the wrong thing and we're just going to make it easier for you to do the wrong thing so um and what is it that they're going to do what they're going to do here is they're going to do this they're going to go along these lines we're going to do something like test constructor and you can see it's a very simple way of generating a test is empty and what else I guess there's going to be a test um what we got next fill okay so we've got the as I said this is really obvious because what you have is a one for one alignment now it's going to be really kind of interesting how how are we going to write these so let's go up to this and I will go ahead and do something like new cup equals new cup okay so what am I going to test I mean I've got a new cup now what what are we going to do what's the purpose of this test do I need to put an assertion in or am I going to leave it like that and if I'm going to put an assertion in what am I going to assert so here's what a lot of people will try and assert and they feel satisfied with this because they've now it's one of those things sometimes you kind of look I need a thing to assert look what can I say I've got a reference fantastic it shouldn't be null why don't we want to write this what's wrong with this yeah and this is a Karl Popper philosopher of the 20th century gave us what we now use as a working definition of a scientific theory a scientific theory is one that is falsifiable in other words it is possible that I can contrive an experiment that if it yielded a false result will contradict my theory and thus I would know my theory is not true and I was I can do something to demonstrate that it doesn't work and the problem is the only way I can make this fail is by hacking the JVM and I think that's a little bit naughty because we're trying to write a cup okay there are no circumstances in which this will actually if new fails we bomb out with an exception if the constructor fails we bomb out with an exception we'll never reach a point where that is actually not not this is just a fancy way of saying a search true true now it's not just this one because it's not just this is a very obvious one but I do find a lot of test cases where people will assert things that are true of the platform in other words there's no case that would ever result in false except if the platform is broken it's entirely possible when I'm referring to platform I'm also referring to middleware and standard libraries and things like that it is possible that these things break but that's not the job of the cup tests to check yeah that's a separate set of tests if you actually have this as an issue then these are conformance tests yeah if you if you require a particular behavior from a third party library and you know that that third party library is a little bit ropey then maybe you have a separate set of conformance tests in other words that defines your precondition but it's nothing to do with a cup it's conformance tests on that so there's a scope issue which now leaves us with nothing to test sadly now sometimes people will say well it's okay because what you're actually doing is you're asserting that the cup constructor doesn't throw now that is certainly true but I feel a little uncomfortable with that because it hasn't really tested the constructor it's tested something very specific about the constructor it's testing that the constructor does not throw which is not the same as testing all of the behavior of the constructor the name the name suggests we're testing the behavior of the constructor but we're actually only testing one thin slice of it we're testing that it doesn't throw now at this point we suddenly realize you know what there is something we could test and I'm expecting it's entirely reasonable that a new cup is empty okay so we've got that right so that seems not unreasonable until we come to the next method which seems uncannily familiar we've kind of already tested this behavior now sometimes what people will do is delete the test case for test is empty but wait a moment it's a Boolean the last I checked Booleans have two values we've only demonstrated that it returns true so and you know what I'll get rid of that so we're going to fill the cup because we already know that the emptiness case works because that was covered in the previous case we're going to fill the cup and we're going to assert that it's not empty heck we may even spell that correctly um so we're going to do that now that's kind of interesting because in order to deal with that we've just had to use fill but test fill is the next method so what are we going to do here we've already kind of tested fill well this does raise the interesting question of what happens if you take a cup that's already filled what happens if you fill it again do you get an overflow exception yeah so let's test that that seems entirely reasonable so what we're going to do is we're going to take a filled cup and we're going to fill it again I think we're going to go for the idea that there should be an overflow exception but I'm increasingly uncomfortable with this because again I haven't really tested fill I've tested an edge case of fill I've tested the main the main common use of fill was actually tested in the previous test method so this one doesn't really work and then and then we end up with drinking let's fill a cup let's drink from it and then assert that the cup is empty that seems to be okay but then we realize there's another edge case of drink why happens when you drink from an empty cup I'm going to say that that's okay you're just going to feel very unsatisfied but I'm I don't regard that as a problematic behavior that's not a negative test case so a lot of developers will then kind of sneak this one in they'll go oh okay right well what we'll do is we'll just say that that's okay now I look at this and I've got in this test case I've got two cases and they kind of mesh together it's very difficult to work out what's really be there's two things this is sort of a I'm testing subtly that that's okay but it's a very subtle thing if I look at this without knowing what our the discussion we've just had I'm going to look at that go why on earth is why on earth is he writing drink and then fill and then drink what possible purpose could this serve and again we have that really subtle case of I'm trying to test that it doesn't throw but I'm not really saying as such now when you look back over all of these test cases you can see that this alignment this one for one is completely dysfunctional it is actually a bad testing style but it is the most common testing style we've ended up with cases of behavior being cases of dominant behavior the fill behavior the main common day use or fill is not tested in the test fill that's an edge case of it or a negative case half of emptiness is tested in one case but the name is empty test is empty actually suggests that all of the is empty behavior is tested somewhere else but it's not only half of it is and that actually evolves fill which is and then I've got this final test case which actually tests two things one of them very subtly it's a mess and this is because it lacks cohesion you know the criteria for cohesion for a test is slightly different to the criteria for cohesion for an ordinary method which is unsurprising because they the purpose of a test is different it cuts across it's a usage it cuts across a class interface now if we go back and start saying well what were we actually saying are we testing the oh yes we can really screw this one up as well if I get rid of the constructor because I'm using field initializers or initializer blocks then it's likely I would never write the test constructor case what we're actually doing is testing construction or we're testing an initial state and if I ask somebody please tell me what's going on here what are you doing in your test constructor well what I'm doing is I'm testing that new cups are empty well that's very different why didn't you say that in other words it goes back to the time honored in other words say what you mean if you meant to say we're testing that new cups are empty why hide behind this veil of test constructor if you meant to say testing new cup is empty then go ahead and it's a lot clearer if I wanted to have the case that new cups should if I for whatever reason I wanted to emphasize let's just say we'd had a bug report against cups that were that threw exceptions in their constructors then I would introduce a new test case test that new cups did not throw exceptions very simple now you'll notice something else I've done there which is a kind of a subtle thing I'm going I'm about to get rid of the test prefix J unit three requires it pi test requires it if I remember correctly groovy still requires it a number of testing frameworks require that you prefix your test cases with the word test I think this is as far as I'm concerned we've already got it prefix with the word test at test it's a bit of a giveaway it's just noise words I don't find that there's a great deal of value to it but there is a practice here that is worth emphasizing if you are going to use the test prefix never ever use test on its own always use test that for the simple reason that grammatically in English test that requires you to place a full sentence after in other words test you can't just test that constructor what that one there you have to test that constructor does something or test that initial state is you have to test that something is the case you have to test that when I do this that follows so there's this idea of test that is a useful linguistic trick of forcing you into writing a proposition rather than simply writing an imperative so you know if you're going to do that then I'll leave it as that I have an interesting one with a group group of C programmers at a company we wrote the term test has a great deal of baggage associated with it it's one of the reasons for example the behavior driven development actually shies away from the vocabulary of testing the terminology of testing has associations for many people and that was certainly the case with the C programmers so we basically changed the approach I basically said during the course let's just call it require that in other words I want you thinking in terms of requirements require that this is the case and that turned out to be very helpful to the point that actually that team kept that as a practice afterwards I prefer the brevity of a new cup is empty if you come across BDD there's this emphasis on use the word should now I am going to say that I'm not particularly wild about this but if it helps you get this style of testing then I'm all in favor of it but as you can see it's let's put it this way I've noticed this particularly in Java in some programming languages and cultures there is a problem with the brevity of names this does not appear to be a problem in Java where people are quite happy to sort of say well to read my code you will need an HD screen preferably a double headed monitor because the line goes over both monitors anything that can save Java programmers from writing these ridiculously long names that they sometimes write where you end up with factory controller, process manager blah blah blah and then the thing that it actually does I think is a great help so for me if I have to put should be then that's one extra word and as far as I'm concerned it's a noise word most most writing guidelines tell you to avoid using sort of equivocal language like should is it or isn't it make up your mind tell me it should be empty you know what it either is or it isn't and you need to state that that's a requirement I can challenge this requirement a new cup is empty I may say no no no our cups come prefilled that's great but the should when that test when this test fails then I immediately know what the problem is this is what I refer to as propositional style naming because it is a proposition a new cup is empty that is a proposition it is either demonstrated it is either true or false if that test fails I immediately know from the name what is wrong I'm not gonna know why but I know what a new cup is empty well apparently it isn't okay you can just tell by the negation of the name if you say a new cup should be empty you know what if it isn't empty we're saying the use of the word should suggest that it's okay to not be empty and where are my keys they should be on the table immediately suggest that it's okay if they're not we're admitting the possibility that they might not be on the table I don't really want that from my tests it'd be great if we replace all the programming language structures instead of if and else and all the rest of it you know perhaps and possibly and you know it's okay if it doesn't and there may be I think it would be make an interesting experiment so I'm gonna say if should helps you go for it on the other hand yes that again there's a whole lot of little naming tricks that people use to help them achieve a certain consistency I'm sort of for them as a kind of a starting point but I find that some of them hold you back I'll look at an example in a moment that kind of holds you back so sometimes we actually find that it forces you into a slightly false style of English it doesn't allow you to say what you want to say on the other hand again if it's one of those habits that helps you then I'm all for it yeah yes I think that that I think that that can be the case but I don't think it's necessarily I'm kind of interested in a broader view I'll look at another example in a moment sort of say well here's where it might not work quite as effectively but on the whole I have no major problem with that except I have seen some people use the it style and they end up with really convoluted English you know in order to fit the it they've had to rearrange everything else in something that's a bit clunky and quite frankly I'm bored of stacks they get you know after you've been doing objects for a few years and you've seen a few stack examples and test driven development yeah that's a few stacks it gets really quite boring recently used lists are much more exciting because a recently used list is like your recently opened files menu it is like a stack the most recent item goes to the head it has indexing but you also require uniqueness in other words when you reopen a file on your recently opened files list it goes to the head rather than rather than ending up occurring twice so it is like a stack and it is like a set it has two properties so it's a little more interesting now obviously based on what we've just done we know that this is not the right way of going about it and the way we would like to think about it 97 things I got I got a really nice contribution from Gerald Mazaros now Gerald wrote X unit test patterns which is about a thousand pages long it's quite a hefty book it has a lot in it obviously but it's one of those books that if you can't convince your colleagues by the skill and wisdom of your argument just hitting around the head with it because a thousand pages weighs an awful lot Gerald said so so that's okay that's a lot of tree anyway I'm going down to about 500 words for this write tests for people first of all you're writing tests for people rather than for machine execution but there's another observation here who should you be writing the tests for for the person trying to understand your code notice that Gerald says for the person trying to understand your code not for the person trying to understand your tests because good tests act as documentation for the code they are testing they describe how the code works for each usage scenario each test case is a case of usage it's not you know so where you find that you are testing multiple cases then that's not a test case and what you want to do is this three-part rule describe the context of the starting point of the preconditions that must be satisfied illustrate how the software is invoked and then describe the expected results the post-conditions to be verified sometimes this is referred to as the historically the three a's a range act assert but it corresponds very nicely with the BDD given when then which I tend to find a more useful way of expressing this so given a particular situation when you perform a particular action then there is a particular outcome if we go so if we look at the recently useless tests do this as C sharp and N unit this is one of the other things when people focus on this more literate style of testing they automatically assume that they need a special framework for it you don't need it you can do it even with just asserts raw language asserts if you need to it is the sensibility I tend to find that a lot of people often take on a framework they have no idea what they're doing and now they don't have any idea what they're doing with a more powerful framework it helps to know what you're doing you want to be able to express yourself what is the means of that expression so to emphasize the real aspect so I've used namespaces and fixtures to basically give me a nice hierarchical structure a new list is empty an empty list retains a single edition retains unique editions in stack order non-empty list is unchanged when head item is re-added moves non-head item to head when it's re-added any list rejects edition of null items for example so that would be part of the spec there are other ways of arranging this again there are the shoulds and the it's and there are lots of different conventions I tend to find that most of those and there's one that occasionally pops up actually putting the given whens and thens in the names but I've found that in almost all cases those end up longer or less less wieldy more unwieldy than trying to express what you're trying to do at this level another example that I've found is a very oh yeah actually I'll have to look at the body of this so one of the things I can do is we can see simply given when then structure if you don't comment them in just put blank lines between them because it helps people understand what on earth it is you're trying to do one of the key properties of this example-based testing approach is that your tests have a very linear narrative they have a cyclomatic complexity of one you start at the top and you go there's no decisions there's no ifs, elses, foes, switches, whatever that's a benefit in the sense of it's easy to reason about this is one of the ways that you know that your tests are more likely to be correct than your code because you can see that they are more likely to be correct I'm sure we've all encountered cases well I've certainly seen a lot of test cases where the test case is more complex than the thing it's trying to test and therefore is more likely to have bugs in Tony Hall, computer scientist Tony Hall observed you either make something so simple that it is obviously correct or so complex that it is not obviously incorrect and I've seen a lot of test cases that fall into the second category the test passes I think it's okay but I'm not sure so you end up with the linear narrative it's worth putting spacing in because you need to break up to illustrate this three-part narrative to the reader now a side note a client of mine a client of mine a few years ago wanted me to review their test cases and they just started unit testing I said yeah fine and they had three test cases test one test two I think you know what's coming test three so we had the discussion what is it that test one does they told me and I said what there you go there's your name what is it that test two does and they said well it tests two different things what do you mean and I looked at the test code and it did test two different things the second half of the test method shared none of the variables of the first half it really did test two different things we don't call that test 2a and test 2b we split it up and you know name it appropriately my favorite comment though came with test three it's when one of the developers sat back and it's kind of like well kevin this is where your naming scheme doesn't work I said why we don't know what it does I said wait a minute you don't know what this does and that's my problem let's be very clear about this what happens when this test fails we don't know because we don't know we don't know what the failure means and I said well this is even worse what happens when it passes we don't know what does it mean when this test passes the only thing that it means is it does whatever it did before we don't know that whatever it did before is correct but we know that it's doing whatever it did before whatever that might be as a minor point one of the other things I've done here which I didn't mention this is C-Sharp in .NET naming style one does not use underscores like this but it turns out that human beings are not very good at reading reading Roman alphabet based systems longer than about 20 or 30 characters so multi-capitalization is a really bad idea above 20 to 30 characters quite simply because of the way the language is structured and our human perception is structured even if you can read German I find this is more acceptable to people in the .NET world when I suggest this in Java people throw me out of buildings from tall floors they just need to get over it rather than throwing me out of it plain and simple people need space separation the whole case separation thing only works up to 20 characters it's based on a thinking error about how people read I've got children I've learned how kids do and do not read and it's really not the way we think they read there's a whole load of visual distinctions that are not significant anyway that's a separate discussion I offer that to you as a consideration but not as a primary practice so let me look at something else leap years now this is a very simple example importantly it's a non-object example I want to demonstrate that the same thinking applies it's not an it's not an object thing that your usage of something is in a particular way this partitioning of tests if I were to do this in the traditional way I would have test is leap that's not how we're going to write it what is the rule for a leap year determining whether or not a year is a leap year this is the reason I choose this because it turns out that everybody remembers oh yeah it's every four years and then there's some exceptions and sometimes people remember one or two of the exceptions sometimes they misremember one of them they're not entirely sure and this is a beautiful example of the problem of what do you mean by it works because if I just simply have a method called test is leap and it passes as a reader I am no wiser as to what the leap year rule is than when I started the challenge here is not to write code that implements the leap year rule the challenge is to describe to the reader what the leap year rule is and the reason that leap year I love the leap year rule because it's a wonderful example of an exception to an exception humans are very very poor with exceptions to rules and very very poor with exceptions to exceptions to rules again with kids I noticed this one my older boy a couple of years ago dad I know how many I know how many days though are in a year he proudly declared I said how many 365 I said yeah do you know about leap years no well every four years it's 366 days there's an extra day in February oh he wasn't sure what to do with that but now he's digested it he's you know 10 years old he's that's he's got that one worked out my younger one however is going through the same process dad a leap year is every four years ah yeah accept what do you mean there's an accept dad yeah accept every 100 years it's divisible by 100 oh accept there's an exception to the exception to the exception every 400 years so a year is a leap year if it's divisible by four but not by 100 or if it is divisible by 400 a year is not a leap year if it is not divisible by four or if it is divisible by 100 but not by 400 and in this particular example I tend to I get people to put a a a bounding on it so I basically say common era years year one onwards if you want to do the if you want to do the full example because this is the Gregorian rule if you want to do the full example it's worth keeping in mind that different countries adopted the Gregorian calendar at different dates I leave that for you as homework okay so Britain did it in 1752 I think Denmark did it in 1751 I think Russia did it twice in the early 20th century that's why the October revolution was in October Turkey was as late as the 1920s Sweden is the most interesting case they started they decided to adopt the Gregorian calendar one day at a time for in 1700 they were in the Julian calendar and they thought what we'll do is we'll add a day a year and then bring ourselves slowly but surely into alignment with the Gregorian calendar and this kind of worked okay except they forgot to do it for a couple of years and then they reverted back to the Julian calendar and then they switched a few years later so if you can get Sweden send me the code okay if you can do this local specific I'm interested however point here is we have a definition of what we mean by leap here as a byproduct we also have a set of examples that would describe it and illustrate it so the point here the challenge here is not the logic itself which you can actually express in one line the challenge to the reader is to understand what do you mean by it works what is it that it works it's uh you can encounter situations like this for example uh tax rules they're ridiculously complex you know test the tax rules are okay and there's a whole lot of test smells I often often see test that this is successful well great I wasn't going to test that it wasn't test that this is okay test that this works okay as one of the ones I've seen well yeah I mean good I wouldn't want to test that it isn't okay so there is a there's a point here however this applies to functions notice that this goes back to this question about naming conventions there is no it in this particular case because there's no object under test I also find the should definitely doesn't work a year should be a leap year if it is divisible well no it shouldn't be it is or is not you know do or do not there is no try okay there's no in between state but the key idea here is this idea of testing as a specification now there's a little bit more to tdd than just that James Graham in his book test driven development from bedded sea observe td is fun it's like a game where you navigate a maze of technical decisions lead to highly robust software while avoiding the crack wire of long debug sessions with each test there's a renewed sense of accomplishment and clear progress towards the goal this idea of progress is important it is one of the things that drives people in programming the idea of getting meaningful progress as you work automated test record assumptions capture decisions and free the mind to focus on the next challenge however one of the most important things that is overlooked is the first sentence td is fun there's another point here is that I got that feedback once on in a workshop where somebody sort of said I didn't realize that testing could be this much fun I didn't realize that writing code could be this much fun often we get into software development because we were quite excited by something we found something fun at one point and then we pursued it through perhaps degree and then into work and somewhere along the line all the fun got squeezed out of it and we kind of have to remind ourselves actually there's you know work and work and play should not be so divorced there should be something that is fun but there's another point about this and I want to highlight this here that this goes back to something else I said before I've made a throwaway remark about C people will often find exceptions to why they should not be doing something this is some very simple C test code people will often find a reason to not do something one of the most common reasons I find it's ideal with folks who do embedded work every now and then and they will say well you know this doesn't work in our environment so I quite like the fact that James Graham wrote a book which quite clearly says you know what actually you can do it in this and it does apply to old languages it's just that culturally there's a difference acceptance what I find is that in the Java world it is much more expected and accepted that unit testing is a normal practice whereas I find that in C and C++ it's culturally it's culturally more awkward but people assume that that must be a necessary thing and it certainly isn't this is just for a simple example doing comma separated variables which is certainly more challenging in C than it is in other languages because you have buffers that have particular sizes and you have to make sure that you don't overflow a string buffer and just simply writing out an array of integers as a comma separated variable string has a lot more challenges than in other languages you want to make sure that if you're writing to null what happens if you overflow do you not write any of the digit or do you truncate digits how does this work so these actually define it and so what I did for this is I took this code and then simply listed the function declaration and then all of those are test names but what you actually see is that I've just going to remove the underscores a value to null output writes nothing no values to sufficient output writes empty and so on and so on multiple values to insufficient output writes truncated value sequence so I've defined very clearly what I mean by the behavior in each case now there's another thing here that's worth keeping in mind that's the implementation and there's enough logic in there that I'm satisfied that I've got tests and pleased that I have tests but I thought for a bit of fun I would mess about with this and rewrite it in C++ the demonstration here is that all I've done is I've just going to refactor the implementation the tests are identical which brings us to another consideration refactoring I did this I did this consultancy I got at a company in northern Germany and they put the sign on the room that I was doing you know I was holding this workshop session in and they spelled my name wrong so I put a little arrow before lunch to suggest the change I came back after lunch this this is good this is not a company as a company this is pretty cool you know if you put if you put a correction on a physical sign and it's fixed when you come back that's very cool so just to just to point out you don't need refactoring tools to do refactoring so refactoring is best reasoned about by considering what we might sort of consider what we might talk about as a right hand rule and three dimensions of quality qualities functional qualities of a piece of code the operational qualities of a piece of code so the functional qualities are the semantics the operational qualities are things like memory usage performance other aspects of performance and so on and then there are developmental qualities is the code readable or not is it easy to maintain is it portable these are other developmental things the operational developmental things people often merge together as being non-functional non-functional is a shockingly bad word I invite you to never use it again but if you are going to use it it's worth checking with a dictionary the concise oxford lists non-functional as follows having no function not in working order so when somebody says what are your non-functional requirements you've either got to be thinking you know I want it to have a function or not in working order yeah we want it to break every Tuesday we want it to crash and burn every Tuesday there you go so it's not functioning on Tuesdays non-functional shows a profound lack of imagination we've got two kinds of we've got these kind of behavioral aspects of the system oh yeah we've got the functional ones the semantics and then we've got these other ones and tell me about these other ones what are they well they're not those yeah and they're not those what are you going to call them not those I went to a zoo the other day what did you see I saw elephants what else did you see non-elephants yeah come on we can do better than that as I said I do care a little bit about words and this is important when we separate them out because some of these illities are fundamentally different maintainability is nothing to do with scalability it's an orthogonal consideration developmental qualities are different to these other qualities which are both runtime qualities they are experienced at runtime when I am refactoring then what I'm doing is I am focusing on keeping the functional axis fixed in other words the semantics are fixed that csv example the csv behavior is identical regardless of whether I'm using the c example or the c plus plus example what I want to do is change the developmental qualities I want to change something about the way the code is done the c plus plus example was simpler than the c example I may also do this with code that is less than brilliant I want to be able to take code that is this long and convert it into code that is this long which is one of those other things about going back to the comment I said earlier on people that write a lot of tests tend to write less code or rather they probably write quite a lot of code but they end up submitting less code in terms of what you actually see they actually you actually see the final result is less code there's probably a lot of activity much code has been written but actually what you end up checking in is reduced now it's entirely possible that the operational axis will change the performance will be different but it might get better it might get worse the purpose of refactoring is to keep the functional axis fixed improve this axis and this one goes either way hopefully not too far either way if you are optimizing then that has a different profile but it is surprisingly similar it's a behavior preserving transformation the functional axis should remain fixed there's no point in having an optimization that doesn't quite work yeah this runs 10 times faster but it produces the wrong answer but 10 times faster yeah so the late john viscides once had to say you know our bugs run faster the point there is you want to preserve the semantics the operational axis is where you focus your attention and the developmental axis may go either way some optimizations make the code more complex they handle special cases other optimizations actually end up reducing the code as this wonderful old saying and it was quoted by a intelligent guy to designing programs remember there is no code faster than no code the ultimate optimization but in many cases we find there is a reduction now we can go ahead and we can see this is an implementation of the recently used list that I had on one training course some of the guys on this training course produced this one they sort of said kevlin I don't think we've done this right because actually to get the exact behavior you only need this much code but the point is you can refactor from the left hand side to the right hand side in the presence of tests in most cases if I did not have this if I did not have tests but I had some kind of indication that the code was correct in its semantics I would leave this as it is because it works right kind of you know if I touch it it might break so therefore even at even at a code fragment that fits on one slide I would be reluctant to start changing it what am I going to do when I'm presented with hundreds of thousands of lines of code so there's this point of light this is kind of sense that the code has become the liability we have not documented the functionality let's go back to that quote and realize that your tests are your way of responding to functionality as an asset in which case if it's an asset please tell me what it is your tests describe here is the functionality thank you very much your code is a liability here is the code we produced you know what that feels like a first draft I'm not comfortable with that but because we've defined what we mean by the functionality we can work against the asset and reduce the liability even in an example as small as this we actually see that coming to life now the final bit I want to pick up on that observation of learning about your code Resistentialism it's a lovely word it was coined in the 1950s if I remember correctly the belief that inanimate objects have a natural antipathy towards human beings and therefore it is not people who control things but things which increasingly control people you may have had days where you feel resistentialism in action where the objects in your world are resisting you and causing you problems so so resistentialism raise just raises the Latin for thing and thing is a less technical term for object what kinds of resistentialism do we encounter in software systems well here's one singleton singleton pattern well actually this is this singleton is actually quite good for your code it's a single bolt and what's what's great is that if you drink a little bit of whiskey whilst considering whether or not to put a global object into your code it's likely that you will not put the global object in your code therefore this is why I say this is good for your code singleton is a menace in almost all of its manifestations almost I'm going to say there are a couple of cases where it actually applies it's just that those aren't the cases that people apply them in but this you find out very quickly from a testing point of view is a pain in the backside it's not just a problem from a testing point of view it's a problem in many other cases it's a problem from concurrency it is a problem from library separation and reuse one of my clients had exactly this situation but they managed to get rid of almost all of their singletons after I visited them a few times they managed this and I remember one visit they were trying to create create a configuration that allowed them to run their server either multi-threaded or as individual multiple processes at the flick of a switch and it turns out that there was they couldn't do this easily and it turns out that one remaining singleton in the system was was preventing them from doing this in other words a singleton documents an arbitrary assumption about how something should be executed and unfortunately it nails it in place it prevents you doing certain things so singletons are generally problems all over the place it's not I don't just object to singletons because of testing I objected to singletons long before test-driven development it is that they become more visible when you test and in other words it's not you're not dealing with the problem because it's a testing problem you're dealing with the problem because it's a problem and testing has made it visible which is slightly different there are indeed we find in many other cases we find that objects are merged together separation is ultimately the issue we find classes that are too large have too many responsibilities are coupled to too many things you want to test a piece of logic but you discover you have to initialize a database it's not that you never want to test the interaction with the database but actually that's not the same as testing the individual piece of logic you really want to keep these separate here is the logic I'm wish to test and then here is the interaction between these two things I would like to integrate that knowing that this is most likely correct then I can be free to test the interaction and understand that if that fails and it's most likely to be to do with the interaction and not the logic over here so this idea I also want to step back a little bit from the idea that the difficulty of doing a test is just to do with the complexity of your code that has become a kind of common mantra for many people they assume I've seen a lot of very respected individuals who advocate TDD say if you're struggling with your test then it's a sign that there's a problem with your code that's too simplistic it's a sign of one of two things one is complexity and the other is knowledge or to be precise the lack of knowledge ignorance and those break out into two cases so the complexity case breaks out into essential and accidental complexity the essential complexity right what is the essential complexity uh how hard is it to write a hello world program this isn't a trick question yeah simple good good so that has low essential complexity the nature of the problem is fundamentally simple last year NASA landed a one-ton probe a roving vehicle Mars Curiosity on the surface of Mars using one of the most preposterous and complicated entry descent landing sequences in the history of spaceflight having traveled between the planets the probe aero-braked in Mars's atmosphere it slowed down by using Mars's atmosphere the problem is Mars does not have much atmosphere so it couldn't fully decelerate so it ejects the heat shield and then outcome the supersonic parachutes to slow it down but the problem is Mars doesn't have much atmosphere so you jettison those and you get secondary parachutes you're still going quite fast but here's the next bit you come down you then jettison the parachute and using thrusters you lower the probe to within about 20 meters of the ground whereupon you lower a one-ton probe larger than most vans to the surface using a crane and then you throw the the rest of the land apart away basically it has to jettison itself away all of this is done automatically because there is a seven-minute light speed difference between here and Mars at that point so this all has to be operated automatically how hard is it to do that it's a little bit hard hello Mars is a lot harder than hello world in other words sometimes it's hard to test something because the problem is fundamentally hard and i'm sorry there's nothing you can do about that it's the nature of your work so now we've got that one out of the way let's deal with the three that we can deal with because there's the other one the accidental complexity which is it's this hard because we made it this hard it's this hard because of the architecture it's this hard because of the code quality it's this hard because of something that we and i use it collectively it may not be you individually it may be somebody else it may be the technical choices that are made by somebody you've never met but ultimately it is a created thing and therefore in theory it is uncreatable you can create a different system a different solution so that may be a different point so you need to distinguish between the two kinds of complexity and then there are two forms of ignorance uncertainty over what the code should actually do sometimes the challenge is i have no idea what this is supposed to do sometimes people refer to that as a coding problem it's not a coding problem it's a fundamental question of requirements and architecture how is this supposed to work now it turns out that sometimes people are very happy to create fictional behavior programmers on a daily basis make up behavior for applications ah what should this do i think it's logical if it does that just remember you are not your users they do not share your belief in logic so we make up requirements it may turn out that the difficulty in writing a test is a difficulty in understanding that you can resolve by going and talking to somebody it may also be a lack of testing know-how sometimes it's not obvious how to test something it really is quite hard if you don't know about mock objects then there's a whole class of interactions inter-object interactions that are difficult to test once you know about mock objects it becomes easier to test them if you are testing algorithmic code then the chances are you can't just do a simple assert on a result typically when we're dealing with number crunching you actually have to do something a little more sophisticated you have to think around the problem you have to almost create new testing techniques so it may be the obstacle is a lack of knowledge and technique so i'm going to close with this observation from Michael Feathers in the software industry we've been chasing quality for years interesting things there are a number of things that work as i said at the beginning the testing is not the only game in town but it's one is part of a broader spectrum all these techniques have been shown to increase quality and if we look closely we can see why all of them force us to reflect on our code there's this other thing when people say testing will slow me down it turns out that what sometimes when people ask me this they're hoping that i'll say no it won't it'll speed you up they're very disappointed when i say yes you're right it will slow you down but it'll slow you down in a good way because it'll force you to reflect on your code there is a friend i don't know if he's still alive you'll understand why in a moment and you just over 20 years ago and well let's try and understand there's a very simple and obvious answer to the following question why do cars have brakes i want the simple and obvious answer that is correct so you can stop that is simple obvious and correct there is another answer that is more subtle and is also correct cars have brakes so you can go faster i want you to consider for a moment how fast you would go if you did not have brakes in a car my friend alan drove from London to Brighton which would normally take you about an hour and a half yeah about an hour and a half in a car with no brakes no working foot brake this is why i wonder whether or not he's still alive i've been in a car with alan when he did have brakes and that quite frankly was scary enough but the idea of him driving a car without it took him hours it took him absolutely ages because he had to take all the back roads he had to use hills careful gear changing and the handbrake at various points to do this this is an insanely dangerous way of driving so when we talk about the idea that tests will slow you down yes tests are your brakes they will allow you to go faster for the very reason that they slow you down and that is a sort of fairly key observation so that's the magic it's why unit testing works when you write tests TDs do style or after your development you scrutinize you think and often you prevent problems without ever encountering test failure sometimes people are disappointed because they think of tests only in the context of quantitative feedback in other words i am testing my code i expect to find bugs because then i know my testing is good it's really disappointing when i wrote my code i wrote my tests and i didn't find anything well those tests are useless yeah why did i bother that's the wrong way of approaching it but still many people approach it like that so on that note it is lunch and i am around for today and tomorrow if you have any questions feel free to ask me thank you very much for your time