 Hi everyone. So I'm Mike Simonson on Twitter. I'm a web developer. I am one of the maintainer of Doctrine for those who know the tool. I'm also the organizer of Brussels PHP if there are people from Brussels that are interested or if there are people that know any company that is willing to host us. I'd be very happy to talk with you after the talk. And I also worked at CubeSolution. Whenever I'm not behind my computer you can probably find me hiking somewhere outdoor. Now that part is done. What do you mean by screen? No, it's apparently the best I can do. So I suppose everyone here is a PHP developer but who here is used to doing TDD at work? Okay, quite a few people. Who is doing TDD like for more than five years? I mean that is quite experienced, okay. I hope I'm still gonna give you a few tricks but this talk is basically everything that I've learned along the way going to conferences and meeting people from very different backgrounds. For instance maybe some of you know drawer helper. I'm probably butchering his name but it's a C sharp developer that gives a very similar talk in C sharp but most of what he learned me is applicable in any language. And if you want to learn stuff about unit testing he has definitely very interesting stuff to say. Who here works agile at work? Also pretty much everyone. Who here works, I mean the boss, their boss says that they work agile but in fact they just do waterfall? Okay, so as I said that talk is going to be mostly about my experience but I think it's a lot of you will based on your answer a lot of you can relate to that experience. My first experience with unit testing was at school where basically we were more learn we were more teach how to delete the test that just failed because we changed some piece of code and just do something else like test another part of the code than anything else. In a way I could see that it might be useful but it was very frustrating. After school I went to a British company for my internship and there they really practiced the right way I would say or at least the first useful way that I had seen. It was a very interesting experience for me because that was the first time that I could see someone developing new code using TDD in a way that wasn't cumbersome and wasn't just making me waste tons of time not knowing where I was going to go. So then I went to my first big job. It was a very big company with lots of developer and apparently no one was interested into building code that actually worked. So I was mostly trying to do tests myself but I was the only one to run them. I was also the only one to write them and the only one to fix them because I was the only one to notice when they break. That was also very frustrating but yeah life goes on and I changed job to go in a much smaller company where I was heavily encouraged going to conference like first them and that's basically at those conference that I learned most of what I know now. I'm mostly going to speak here about unit testing but that's just one part of all the tests that you can do on your application but before to speak about the different kind of tests to see where the unit test stands there is also the pretty obvious question like when should we test. It's always a cost-benefit question at some point like the product has to shape and you have to get paid so you have to know when to test and when not to test most of the time I'd say that it's rather a question like is that project going to live on after I finished working on it like am I going to give that project to this project responsibility to someone else is someone going to maintain have to maintain it. If the answer is yes then it's probably a bit I mean it would be nicer for him to test it it's going to simplify the job of the person that comes after you a lot especially because we live in an industry where we are asked to build prototype and all those prototypes end up in production so if you want to know when to test basically ask yourself the question if you want your project to succeed or not. The unit test in the wall test scene is basically the one that is at the bottom it's the test that is the closest to the logic of the code the one that is the fastest to run because it has the least dependency if your unit test has a lot of dependency it's not a unit test anymore it's basically a functional test or an integration test and the fact that it's fast to run because it has no dependency make it cheap to run and make it interesting in the sense that if you run those tests a lot then they are going to be useful. The only good reason to write a test is for the test to fail if the test never fails this is just useless it's just wasting time and space I suppose everyone has seen a unit test here the example is in Java but it's pretty much the same in any language you just have a method and some random class that is marked one way or another in a way with an annotation or whatever else exists in your language that is similar to annotation and does the same job to mark that that method is a test. What I give you is effectively the fact that you can have a piece of code that can detect that automatically and you don't need to program that part of the work it's just going to pick up whichever test you have anywhere in your in your code and run them automatically it's a contract between between you and your unit testing framework. The first issue that I had when I was in that big company trying to implement or and run the test myself was that I didn't really knew a lot of tools that could help me and now it's really easy to use any one of them I mean they're all over the place any unit testing framework has its own test runner you also have a build server that you can install to run your test on a separate machine and you can even implement in really simple fashion a script that picks up every time you change your code and run the test that way you don't even need to either way go out of your IDE if you use one and run the test it's just going to happen automatically you can have on one screen your tests that are constantly running and working the other without any issue the build server is also important because as opposed to what I was doing it gives a way to show the test result to the other person in the team I was the only one to run them so I was the only one to notice when they failed it's like if someone cannot see the result of the test in the team obviously it's not that person is going to forget to run them at some point and then forget to use them completely so installing a build server if you're more than one person in the team feels like a necessity to me it became really easy now there are templates for PHP projects in Jenkins I suppose everyone knows Jenkins it's really easy to set up now you should definitely do it there are also IDE runner for whichever IDE that you use there is probably a test runner that's already integrated in it and can provide additional functionality like just run the tests that cover that piece of code yeah now writing those tests you can basically be in two different situations you are either way writing tests for a brand new project or you're writing tests for existing code that you have to maintain let's face it there is way more projects to maintain than new project to do even though there is a lot of new project to do but like I suppose every one of you has had to maintain a project at some point and it's the bulk of the work if you have a new code it's obviously going to be easier to start doing tdd on that code and in that case I would encourage you to take a look at bdd tools behavior driven development tools there are basically a little bit the same the same kind of tool that we have for unit testing for the code they have the same behavior but for the person that actually asks you the feature of that code so by writing scenario and behavior different development it's going to guide you on what unit test you should write so that you can write the code that fulfills those unit test and fulfill those scenarios I'm not going to talk about those tools there is a lot of documentation available pretty much everywhere if you're looking for one in php there is behat for instance but there are other it's just the most well-known sadly if you're not in that case most probably your code will have dependencies like often when you look at block posts that describe how to do tdd they use a calculator example it's really nice because it's really concise but none of the code that I wrote is actually so dependency less than a calculator and as I said previously if you have dependencies and you use them in your unit tests it's going to make the test slow it's also going to be really hard to set up across the machine of all I mean reliably set up across the machine of everyone that's on the team especially if you have people that are windows others that are on mac and linux and it's also going to be a pain to set up on the ci server if you have one some of those dependencies are a little bit more subtle than others often people don't realize that the time is a really annoying dependency and I remember that when I was in London one of the tests that I fixed was a test that failed six months on the year and it was basically just an issue in a day calculation that wasn't taking into account the yeah the daylight saving time it's really hard to figure out that is the issue if you don't see the time as a dependency of your code and try to extract that dependency in a very explicit way one of the way that I've seen people deal with those dependencies is creating what's called fake object it's really simple to do here you have an example with the migration class of doctrine migration it has a bunch of methods and if you need to create a fake object for that you just extend migration and override all the function all the public function of that object without putting anything in the body of the function and you have just an object that is really similar but doesn't do anything it's really easy to do that like if you start testing but it's going to be a pain really really fast because every time you will change something in the object that you extend you're gonna have to change it also in the fake objects that's a lot of code that you have to maintain yourself every code that you write yourself you have to maintain yourself and and that's it now there is also who heard already about mocking frameworks okay most of you so I can probably go a little bit faster there but it's basically a piece of code that will do that work for you automatically so every time that you change something in your object it can regenerate that fake object automatically it can also provide a lot of additional functionality on top of that for instance you can verify that certain methods of your object have been called or have not been called which is much harder to do if you implement the fake object yourself here you have an example of one of the mocking library that exists in PHP it's called mockery there is also a lot of other there is prophecy and even PHP unit has its own mocking library but mockery has very interesting feature like for instance one of the things that's annoying when you have a lot of stuff to mock in your code is that sometimes you have to create a lot of mock object that return each other until you have actually mocked the dependency that you wanted to mock and you can do that at once with mockery which is nice although it might mean in the first place that your code has a problem of structure if you have so much to mock but if it's just code that you have to maintain it's a really quick fix before you can refactor that piece of code any question yet no okay um now um I don't know if anyone heard about automocking container no okay I'm gonna learn you something sadly that's not something that exists in PHP yet at least I couldn't find any implementation but it's that idea that in most framework now they have dependency injection container that you configure so they can create the object that you need in your application and they reuse that container to automatically generate mocks so because that dependency injection container already knows how to build the actual object it can really easily create that object only passing its mocks so you have actually the real object it's just cannot do anything on its own um now the the time dependency uh the solution to to fix the time dependency is basically to pass the time every time you need to use it if you have daytime now anywhere or daytime without any parameter anywhere in your code it's gonna make that piece of code really hard to test uh and you should probably pass that information uh at at at creation time so it looks like that piece of example is okay sorry um this is actually showing how you can you can do that pass the time uh without having to change too much if you do it at first you can implement an interface a clock interface that just return the current time and uh then you can implement two class a system clock that just do that uh return daytime now and a mock clock that's and a mock clock that is going to return the time that you decide in your test okay i'm sorry for the order of the slide here but yeah the first one was showing the problem but um here by passing the clock and asking the clock the current time we have actually fixed or dependency issue to the time if we have any test that needs it you we can just replace uh the system clock by uh the mock one and pass it the time that we want to use in our test uh it's mostly useful if you are making calculation but it doesn't take a lot of time to implement so i would recommend to take a look at that solution now it's all good but we also have a big problem in the documentation of this of the unit testing framework in general um because they never really explain you how you should structure your test or how you should write them because you have that freedom in that method of your unit test where you can do anything you want um yeah it's maybe a little bit hurtful in that sense um and often the the information that you can find at least in my opinion uh make you end up in uh with tests that are really hard uh to maintain maybe we can uh come back to the definition of the of a unit test it's an automated piece of code that's a really important one because uh at the the company where my girlfriend worked uh they had unit testing that they told her while they hired hired her it was just some person with an excel cheat file that was just running the test by clicking on the button in the interface that's not a unit test it's a unit of work of the system um that one is really hard to define uh i've not seen anyone yet that could give me a proper definition of that um the only thing that i can tell you is that to me uh a unit test it's a test that tests the smallest possible blocks of code and you can check that if you use uh code coverage often you will see people that use code coverage as a sort of a vanity uh vanity thing on their read me on github uh yeah i have a hundred person code coverage but that doesn't give you any indication on the quality of those tests uh if they are easy to understand like what they're actually testing and if you're if it's going to be possible to modify them or not that's test should check one and only one assumption about the code that one is a really important one as a doctrine maintainer i sometimes read pull requests where we have tests there are like 200 lines of code and you will see someone that do something then assert something then do something else then assert something else and it's actually impossible to understand what he's trying to test or what he's trying to do in that test test one thing put what you're testing in the name of the method and the person that comes after you is going to love you it doesn't actually still give you a lot of information of the structure of the test yeah as i said one of the important stuff to test the quality of a test is to make it fail first if the test didn't fail you're can never be sure that it actually tested what you expected to test that's something that happened to me countless time writing tests thinking that they work and never see them failing because they were actually not testing what i thought at all as i told you the code coverage which is the really way better use trying to determine what you're testing than trying to give you a good feeling by showing a high percentage that the best way you can use the code coverage is is trying to cover only one test you run one test and you see how much code it's covering if it's covering hundreds of lines it's not a unit test anymore it's probably going to be slow and it's going to be much harder to understand what it's trying to test okay what is that example i'm sorry um yeah that's the test that he's trying to test no that's another problem of the code coverage often you can end up with a hundred person code coverage and you think you're safe except that in that case you can write three tests that will co will give you a hundred person code coverage but they're not giving you uh they're not testing all the possible scenario that that code can be in because um actually maybe it's better asked like how many tests do you think you have to write to cover all the scenario of that example so who says three who says four five six twenty seven uh how do you reach that number three three three power three i think it's three uh factorial but i'm not sure i would say it's three factorial three to be sure that you pass in all the if and then one more because you could pass in none of them but anyway it's that that piece of code could give you the impression that your code is tested and it can still end up in a situation that you did not expect how can you detect that it like it's really hard to know if your test is good and the only tool that can help you do that is mutation testing any any one of you heard about mutation testing okay quite a few people um for those who don't know um again it's the idea to try to use the code coverage in a slightly different way uh we have a PHP tool to do that it's called humbug it's actually going to run your test using code coverage so it can map each test with a piece of code that is covering and uh based on that it's going to change logic in your actual code it's going to randomly change greater than into lower or equal and that kind of change that are actually uh syntaxly correct but will change the behavior of your test and then it runs the test that covered that piece of code and there can be only three solution either way the code blow up the test catch the failure or the test doesn't see anything and it's actually that part that interests us um if your test did not catch a change of behavior of your code it I mean it probably means that the test is not that good the the problem of that kind of tool is that because the change are randomly generated over your code you have to inspect the change that it did because it could have uh no actual change in behavior it's just the syntax that change in PHP but that's something that you have to go through manually so it's quite slow but it's still very useful um to to determine if your tests are good as I said because it's going to try to map your code to the piece of code that is covered by that uh test if each of your tests cover hundreds of lines it's going to take forever to run that kind of tool and it's going to be even harder to uh try to interpret the result of that tool so for instance on doctrine we cannot run it because it would actually take pretty much amount on my machine so we have a lot of work to improve the test now on the actual structure of the test the best advice uh I've got this this comes from drawer actually um it's I don't know a bit weird that I could never read about that anywhere but I hope that you're gonna find it interesting um you can read about that everywhere what is AAA anyone does anyone know what AAA AAA is sorry yeah that's also bad rates uh in the field of unit testing AAA is um that idea that you should have three uh parts in your unit test the arrange act and assert part of your test um it basically mean that in the arrange part you set up something then you act on it you call a method on that uh piece of code and then you assert a certain result on it so here we are building you just a collection adding an element to it and then checking that the element is effectively in the collection object or not um the problem is that there is no way to enforce that kind of stuff like you really have to read your test and see if they're actually following that guidance or not um it's just a guidance so it might not work everywhere so far uh for me it has always worked but maybe someone has an example where uh it might be not so useful the arrange part of the test here you can see uh an example where uh in the arrange part someone is actually creating two automobiles uh then uh painting one of them and uh no sorry yeah and asserting wait what is this doing so someone is creating two cars with two different colors then painting one window with the color of the other and checking that in the end that the color uh was effectively uh painted on that second color can anyone see any problem that uh could arise if you write the test like that like it's respecting the arrange act assert but if you have that kind of sorry if you have that kind of test um over time it's probably going to be an issue can can someone see why yeah yeah so your object is probably going to evolve and you might decide at some point that having the color as a string might be not the best idea and you change your automobile to pass an object that represents the color for instance or change anything else in the constructor of the automobile and you need to change all your tests you need to adapt that everywhere in all your tests so to fix that the advice that you will see everywhere is oh but it's easy just use the setup method every unit framework uh every unit testing framework provide that kind of facilities uh one method that will get called every time just before running your test it works but it has two issues first it means that now all your tests have a dependency on that setup method and if at some point one of the tests make a change to the object it's gonna it might affect the following tests that can run we have things for that now in php units and most of the time it shouldn't be an issue because it's actually php unit that's gonna make a new instance of the unit testing class and call the setup and call the next test in a completely separate fashion but still you could end up in situation especially when you're trying to mark databases and stuff where one of the tests do a change that gets persisted and then uh the next tests are affected by it and now you're in a situation where the order in which the tests run is actually important so that they don't fail and when they fail you have to start like binary testing all your tests to find which one is causing the issue in your test suite i've had to do that a few times it's really painful so i would advise against against using that the other issue is that although here it might seems like your code is dry because you are only creating the automobile at one place in the setup method and then it magically gets called everywhere if you have a few hundred tests and you just read the test you just see objects that you don't know where they come from that they get that get calls and then an assertion is made and it becomes that much more is harder to reason about the test dry in uh so dry is uh for those who don't know dry is a technique which means don't repeat yourself it tries to uh make sure that you refactor your tests in a way that you don't write twice the same piece of code in the same class for instance or at least that's the way a lot of people understand it that can be a whole other discussion but that's one of the reason people use the setup method because then they don't have to write new automobiles everywhere in their test if you have that test in the middle of a file and you need to scroll at the top to find a setup method if it's at the top and not at the bottom or somewhere in the middle it's just a pain to understand how your tests behave so the next solution that i've also seen maybe i removed that example um yeah extracting to a method to the extreme is also hurtful for your compreation of the test because we've had clients that ended up in a situation where their all their unit tests basically look like that initialize do and then assert again having that test or not having it is pretty much the same now the solution to that problem that you might maybe know the builder pattern who knows the who heard about the builder pattern okay um i don't know why i've never seen anyone use it in unit tests but it actually make the unit test that much more readable and you still get the benefit that if your code changed you have to change it only in one place um for those who don't know the builder pattern is just another object that will create your object for you so here the automobile builder um just uh has a build method that will return your automobile on its own it might not seem uh very interesting but if you use that with a fluent interface so that you have methods everywhere in your builder to change how you can or change the parameter that you can build your automobile with then you end up with tests that are much more readable you actually have an arranged part of your test where you can limit yourself to only specify the stuff that are important for your test it's not done here but you could totally imagine that you have a create builder method but also a create builder with default values that i don't care about and then on top of that you just change the part that is important for your current test the assert part of the test um again can anyone see a problem in the assert part of that test the whole collection exactly so maybe you might have heard that that your tests should only have one assertion um it might be not always the case in the sense that there's some good reason to break that rules but there are no good reason to put an assertion in a forage if you start putting logic like that in your code at some point you're just going to need to unit test your unit test to understand to make sure that they're actually doing what you think they are doing so as a as a base rule it's recommended to only assert one thing the other reason to only assert one thing is that all the unit testing framework through exception when the assertion fails which means that all the following ones won't run and you won't get complete picture of what's wrong in your code now one of the good reason that i've seen to actually have more than one assertion is for instance testing an exception if you need to test the code of the exception but also the message it makes sense to do that in one test but if you write it like that again um if it fails at the error code exception code you don't know if the the message is still the right one or if the message is also in a weird state it's just an example there might be better um but it get the the job done uh to fix that issue there is the concept of assert all it also exists in pretty much any unit testing framework um and it's just an idea that you can write yourself an assertion that you pass assertion to it and it's going to run all of them even if one of them throw an exception and just re-throw the exception that were uh that were thrown in the first place uh at the end of your list of assertion for some reason um i see also a lot of people that want to religiously stick with one assertion type in all their tests and they have assert to everywhere although that completely works um it makes the default error message completely useless when you end up in test suite that breaks a few hundred tests and the only thing that you can find out of those tests is assert true but what's false uh yeah i mean if the test weren't there it was to me it's pretty much the same um so picking the right assertion for the thing that you are trying to test means a better error message and that's what is going to help you fixing the error in the first place we are only writing tests so that they fail so when they fail it would be nice if we could get really fast a good idea of what's the actual problem in the test and also people get the parameter order often wrong so supposedly um most of the unit test from testing framework i've seen the first parameter is what you expect and then uh you pass the actual value that you are testing if you get that in the wrong order it's also going to make the error message really confusing um no another way to have better uh assertion i've it's also something that i've not seen implemented in php but there is no reason why it couldn't be done uh and maybe it exists and i've just not find it it's a library uh that exists in c sharp and in java um and it's called should be and what should be allows you um it basically will change your assertion from the one that's on the top assert same read and then get color to something like color should be read when you read the test all the time that you're don't spend doing that whole gymnastic in your head like oh the first parameter is what i should have and then the second one is what i'm testing it's a lot of time that you are not wasting by just having it spelling spelled out directly in front of you it's it's pretty much english uh uh yeah to me it makes the code the test much more evil um they also uh they also have a very interesting concept of uh equivalence where you can say that two objects should be equivalent but you can exclude some of the property of the object so here in the example you for instance use a uuid in the constructor of your object um if you try to assert that those objects are the same in your unit test unless you have a setter to set that id to null it's just never it's just going to fail all the time on the uuid um in that case it also makes the test to me super readable it's very clear that the customer should be equivalent but the id does anyone has uh any question so what is your question exactly how to write code that use dependency injection or yeah so your question is why is dependency injection or no no i i should probably have asked a question um but uh yeah who who doesn't know what dependency injection is okay maybe people are shy but um um there no it's okay um the id of dependency injection is just that id that instead of doing stuff like that where the uuid for instance is just created using a static method which make it impossible for the person that looks at your code to know that it's actually has a dependency on a uuid library instead of doing that you make sure that everything that is used in your code is either way passed to the constructor if it's necessary at construct time or it's passed to the method that you use um in any case using dependency injection in my opinion is going to make the code more readable uh because just by looking at the constructor you directly know what is necessary for that class to actually do his job but it's also going to be easier to test because in your test you can overwrite all those dependencies uh easily whereas it's much harder if it's a static call or impossible um any other question yeah to be fair it's just an example maybe it's not the best but um to answer part of your question there is about the fact that it's testing at the same time the paint method and the get method i would not expect the get method to have any logic in it so it would be weird that it fails it's totally something that could happen especially if it's a code that you didn't write yourself and code that's existing and that you're trying to unit test but there it's it's just an example um yeah that is maybe not the best yeah you're actually uh making uh your you have a unit test so basically you are really dependent on your implementation so if you change a little bit then all the tests would break but the unit still works how do you see that do you think it's still right or that's already we should we should try to not do that maybe i did not insist on that part enough but mug is uh a fix for a code that is already problematic if you have to use marks too much and everywhere it basically means that your code is structured in a way that everything is dependent on everything and that make it super hard to test and that's exactly what's going to happen something is going to change somewhere and all the tests are going to break uh mark is is only there because you have already existing code and you're trying to test a small part of it um it cannot fix all your code at once do you think the verifiers uh fall into that same category problem because once verify that uh the way of method is run inside that unit it means that that always has to be there even if the unit should work after the practice what do you mean by verify so uh for example i have a uh and then i'm verifying that some methods that probably in that unit you run for example but then someone comes along the line and you factor that method so the method is still output what it was doing before but that method is no longer there and now you're verifying the fact yeah um maybe i should uh use an example where it's actually useful but in the case that you are uh showing it could actually be a problem um i have a hard time finding a good reason to use verify just like on the spot now but um i've seen example where it was partly justified i just cannot find a good one just now we're other time sorry um thank you very much