 Assigned that I'm that I'm supposed to start. Hi. Welcome to PHP unit for Drupal developers I am Sebastian and I've been doing things with PHP on to PHP for a really long time now And when I say a really long time that it that means it's Little bit over 19 years now that I had my first contact with PHP I Grew up at least when it comes to computing and programming in the Amiga demo scene I learned programming in see an assembly machine language on on the Amiga back in the 80s and 90s and at some point Someone who I knew from from that community at some point contacted me and said hey back then you did the 2d and 3d real-time Graphics routines in assembly on the Amiga. That's basically the same thing as programming websites But that was our graphics artist from the team that I was involved in and he was not doing websites and he said well I need something That is not just html, but something dynamic on the website Was it was a very complicated? guestbook that they wanted basically But for you that's exactly the same as what you did back then I said I have never done anything with web development What are the programming languages and he said well you have the choice between PHP and Pearl? And I looked at Pearl for like an hour or so and then decided no, I don't want to learn that And I went with PHP and within a week and I learned enough PHP to implement what my friend wanted and then a Couple of months later. I started to use PHP for real and at some point while I was still in university I came across the concepts of testing and quality assurance and unit tests and J unit and I Wanted to have something like that for PHP it didn't exist and without really thinking about it I started to work on PHP unit and that was some time around Summer fall of 2000 and in 2001. I published the first version of PHP unit and now I'm here What am I doing when I'm not speaking at conferences and not working on open source projects? I'm an IT consultant with the PHP consulting company. I help PHP teams Like this team over there to build better software using PHP and that involves a lot of Things around PHP units writing Effective tests coming up with efficient testing strategies and teaching them how to write testable code Because without testable code. It's not fun That's my company, but I'm not Going into any marketing Some of the companies that I've had the pleasure of working with some really small some really large prop most of them You probably never have heard of some of them. You have heard of I guess, but no marketing The only thing that I would like to say before I start With the presentation is I would like to thank everyone who made it possible for me to be here There was a crowdfunding to cover my travel expenses to get here and if you want to find out Why I need my travel expenses covered then I invite you to read this article that I wrote on on my blog And that's it. Thank you to everyone who made it possible for me to be here so Websites testing. What is this all about? I have this horrible recollection of the first time that I set foot into an Agency an internet web development agency somewhere around 1999 No, that's not that's not right summer 2000 or summer of 2000. I had vacation from University The world's first PHP conference which happened in October 2000 in Cologne had just had published their schedule and I was on the schedule and the company from Cologne called me I Still have no clue how they got my phone number But they called me on a Friday and said hey We we learned from the agenda of this conference that you know something about PHP We need a PHP developer and we know that you are at university and university is currently off So you are free and can you start Monday? This sounded so ridiculous that I said sure. Yes, and on Monday I went there and worked there for a couple of days and then then I left But what I found found to really interesting was they really started This paper and big plans planning for six months and then after six months they started doing things in Photoshop and at some point maybe Photoshop or maybe it was Something else dream we were or something front page in 90s long ago. I'm getting old software that we don't want to talk about so today. We probably would use something like Photoshop Generate HTML from that and then you look at that for the first time in your browser and then you need to tweak it a bit and What do you do when you work on HTML CSS JavaScript and you look at it in your website and you are tweaking things You hit f5 a lot That's the at least the front-end developers main feedback loop. I changed something. I hit f5 and It's really interesting in in hindsight how old this f5 hitting for reload is I reason I actually checked recently This by the way is my second computer, but the one that I still have it's an Amiga 1200. It still works I no longer use dial-up modem to connect to the internet now. It's on Wi-Fi and That works and back then the really early versions of Graphical browsers even for the Amiga you hit f5 to reload and that's how I started with HTML and CSS I'm not sure if it was CSS at the time. They may be just plain HTML On the Amiga way back then so you hit f5 when you made a change to see whether or not the change had the desired effect That's our feedback loop Okay That maybe that kind of feedback loop may be fine if you're just looking at the visual things When you're looking at okay, I changed this CSS rule I changed this tag from an h1 to an h2. Does it look right? Maybe then this kind of feedback loop is okay and sufficient, but what if we change Something in our peach decode something that actually has Maybe side effects. Maybe we have an e-commerce application and even I click something I don't own I not only want to see a new page the next page in the process But I actually want to make sure that I Actually talked to the payment service correctly and got my money so that I can send a note to the warehouse and Ship something so what does our feedback loop look like for php code and of course at least in the early days since Many php developers came from front end. They use the same feedback loop They just made change in php code hit f5 and looked what happened But in most cases for for for application logic for the main logic you need to look deeper So we need to actually open up our Not the computer. That's just for for visualization, but we need to look deeper. We need to look what happens inside the php code on the back end and not just on the front end and Maybe We go to the command line use the php build and web server run in this case our application, which is Drupal send a request and then Use var dump print R. Whatever we are used to to put into our php code to do On the flight testing or debugging The old school way that Maybe qualifies as a feedback loop, but for me like around 1999-2000 When I was exposed to J unit at university with Java, which I never really used in production, but I Like the concept and and the idea of writing Something that automatically verifies that my code works correctly That feedback loop started to feel Wrong to me and that's not really the feedback loop you should be looking for Right, that's the main board of my Amiga with some Lego. That's not the feedback loop You're looking for you don't want to do print R and var dump based testing in your production code Historically speaking though, that's how in the really really really early days testing started you put Additional debugging statements into your production code ran the code and checked whether or not At a certain point in time during the execution of your program The program was in the state that you expected it to be in There are programming languages where that is still a Best practice a good practice today. So see C++ and other languages have built-in constructs The assert statement that is that checks at runtime whether or not The software is in a given state. I mean, it's not in that state execution is aborted That works and it can be used to put some safeguards into into place that you do not run into really bad situations into Into situations that you don't want to be in illegal states of the system if you will But it's not really testing. It's just a safeguard and yes That can be abused for some testing or some debugging on why you're testing But the tests do not belong into the production code the code that actually runs in production and that's the realization that I Don't know who first came up with it the earliest framework that I know that had this idea was as unit for small talk by Kent Beck Which according to legend almost nobody used and Then they had this famous Flight from from Zurich to Atlanta where Kent Beck was sitting next to Eric Gamma and Eric Gamma on his laptop Had Java with him like one of the first versions of Java and he had heard about S unit and he wanted to have S unit for Java and Kent Beck had heard about Java but had not used Java yet So they ported while flying from Zurich to Atlanta as unit to Java and out came J unit and Their idea was okay. Let's take these debugging statements Like what we in PHP would use print or print R or Vardam. They just used a print or a print F Take these statements Pull them out of the production code Put them into separate source code files that we can run When we want to test something and we don't need to put that those files into production Don't need to compile them into the production binary. Don't deploy them have them separate so that we have a separation of production code and test code and that's what all these Test frameworks that are in the tradition of the X unit family of test frameworks S unit J unit CPP unit was the third one PHP unit was It came shortly after CPP unit So so that Can give us a different feedback loop, right? We want to automate our tests Another downside in addition to having test code and production code mixed Mixing things is never a good idea at least not in software development Another downside is that you cannot really automatically evaluate it You always need a human to look at the Vardam output and figure out whether or not that makes sense whether that's the correct state Yes, of course, you can put additional Logic in there and make a check and print something nice when it works correctly or only print something when it's wrong but that's It still doesn't belong into the production code that so we put it out we put it out write it somewhere else and Automate it and make it really easy to run these tests and get useful Information out of running these tests things like how many tests that I execute very successful which tests failed What is the reason why these tests have failed? Where in the code was the application running or currently executing when something failed? Which parts of my application I actually covered by tests and where Do I have blind spots? Where am I missing tests? So that leads us to automated tests and automated tests is a piece of code that you write down that can be automatically executed by a testing tool and PHP unit is two things. It's on the one hand a framework for writing tests for making it as easy and simple and convenient as possible to write down your test intent to Capture how you want to invoke the unit of code that you're that you're testing and What you expect to happen what you expect for the test to be successful? What is success criteria is and the other thing that PHP unit is is a command line based tool that Executes these tests and reports useful information based on the test execution When we talk about software tests, there are many different types or categories of software tests one category already mentioned automated tests the opposite of automated tests is of course manual testing using a Real human with a real mouse and a real keyboard in front of a real computer with a real browser exercising the application And these kinds of tests are really useful when you want to do Usability tests for instance is the user interface or is the user experience? Does it work? Do your users actually understand it and can use your application? Conveniently that's automated versus manual another categorization that now comes into play is dynamic versus static Tests that you implement using PHP unit are so-called dynamic tests because they test the software While executing the software while the software is running That's what you need to do for Testing using PHP unit for testing things like performance in scalability With tools like Jmeter and Siege and others There's a complete separate category of tests from that that is called static testing or static analysis Testing the software without actually executing it. That's what PHP code sniffer for instance does it looks at your code and checks Whether or not it conforms to your coding guidelines or things like PHP copy paste detector that look at your code and tell you Where you have duplicated pieces of code that you should consolidate into only one occurrence of the code or things like PHP stand or fan that actually Try to comprehend the code and tell you okay. You have something you have an area here that is hard to understand That's in the long run prone to errors and hard to understand for new developers that have to work with it Refactors this make it simpler so that it's easier to read and easier to understand the code or to find Bugs and other problems We are talking about automated dynamic tests and one of the most common and popular Ways of implementing these automatic dynamic tests is in the form of unit tests exercise tests that exercise one unit of code in Isolation from all of their dependencies these tests are really precise when they fail they point exactly to the line of code Where something went wrong since they only execute very little codes. They are really fast to execute That's all nice characteristics So let's start I Mentioned earlier that PHP unit is a framework for writing tests and like any other framework There are a couple of conventions that you should follow to get a lot of convenience functionality for free first convention is That the tests for something that is named email go into a class that is named email test Such an email test class then extends PHP unit framework test case that is the default base class for your test case classes Should you have a completely different idea for how you want to write your tests and Still want to leverage a lot and reuse a lot of functionality and code that PHP unit provides You can do that. You simply need to implement a very narrow interface PHP unit framework test As far as I know at least nobody has ever done that And I hope that means that PHP unit framework test case is sufficient and convenient for most people at least the next convention is that a Single test goes into a public method Where the name of the method begins with the prefix test? some people don't like this method name prefix of tests and they can just omit it and add an Annotation with at test in the dock block for that method if that makes them happy I am happy and to each their own but most people just use the method name with the prefix test please do yourself a favor and Think for a couple of seconds and come up with a sensible name for the test That precisely and concisely Describes what it is that you're testing in one of the earliest discussions that I had about PHP unit and tests at a customer Some 15 16 years ago The developers were complaining that PHP unit does not give them useful error messages when a test fails And I said I cannot understand that because you can just look at the name of the test And then you see what it is that you were trying to test and then you see what went wrong and what is currently broken No, no, no, that doesn't work because look at the output and what they did was they just enumerated the test That test one test to test three test 4096 and so on of Course if you don't provide the information PHP unit cannot provide the information when something fails There is no AI machine learning crystal ball voodoo magic inside PHP unit that can Understand and comprehend the intent of what you're trying to test you need to encode That information in the name of the test Naming is one of the hardest problems in Programming a Bad name for a class for a method for a variable can cost a lot of time and Nerves and effort in the long run so Take your time take a couple of seconds if then the name is not clear talk to someone Ideally to a co-worker if a co-worker is not there talk to your elephant or your rubber duck and there's this thing in in in psychology and Neurology that basically says if you have a problem sometimes the solution comes when you Say it out loud because in different areas of your brain are active And it doesn't really matter if you talk to a real human or to a rubber duck or in the case of the PHP community to your stuffed elephant Think about names names are important naming things is important So we want to write a test that verifies that we can create an email object from a valid email address and then inside your test You can basically do whatever you want PHP unit does not care What the PHP code looks like that you invoke you can invoke a global function You can create an object and call a method In some really really really old PHP To code that I saw a couple of one only a couple of years ago that is still in production It's like a 20 year old version of PHP. Why not? They were not even using functions What was supposed to be a function was in the PHP script and when you wanted to call that function You included that script and before that you put the parameters Into specific global variables and they were read from there and they were deleted and the result came into another global variable It works and you can test that with PHP unit. Please don't write such code in 2017, but PHP unit does not care what you do inside the test method What PHP unit does care about is you need to tell it how you want to wear or what you want to verify What is your condition for the test to be successful and for that? PHP unit offers you a wide range of so-called assertions assertion methods like a search instance of or assert equals or assert true assert false and So on use the most specific one possible that expresses What it is that you want to verify in this case we want to verify that we get an email object back That's why we use a certain instance of In case you were wondering what weird syntax constructs I was using there like the double colon void at the end of the method signature or The declare strict types equals one Pragma at the beginning of the PHP source code file I'm of course using PHP 7-1 syntax because that's the current version of PHP and because it's my personal opinion as At least as in when I'm wearing my open source hat at a conference that life is too short for old versions of PHP I know that's kind of risky or Scary thing for me to say at the Drupal event where you still support PHP 5 5, which is very very red because PHP 5 5 is dead dead dead for one and a half years now and But okay, that's my opinion And new code that I write I write using PHP 7-1 which is really nice It's also a lot faster and useless memory In case you need more arguments If you want to learn about PHP 7 That's the only marketing that I'm going to do We wrote a book about PHP 7 PHP 7 explained there's a discount 25% discount for Drupal con attendees I There's one thing that is special about this ebook It's a one-time purchase and we'll you'll receive free updates for as long as PHP 7 is current Even if ten years from now PHP 7.10 is released you'll get an update That covers all the changes all the new features of PHP 7.10 and we are Currently working putting the finishing touches on the coverage of PHP 7.2, which will be released at the end of November early December Which is shaping up to be yet another really great release lot a lot faster than PHP 7.1 Dimitri and Nikita and Xintian are doing amazing work on The compiler and the runtime and the optimizer really cool stuff so Side note and over so this is our test now we can try to run it As I mentioned earlier PHP unit is a command line tool That you point at your tests and it runs your tests and Of course it tells us hey, I cannot execute this because I cannot find the email class Probably because we have not written it yet For each test that PHP unit executes there's one character of output While the tests are running to indicate progress in this case. That's an E. That's the E that we see up there the E stands for error and an error is Or an error is reported When a PHP error happens while running the test like a class has not been found Or something unexpected happens like an exception that was not handled That's something different Compared to an F for failure an F you will get when an assertion fails you as you expect The return value of that method to be an instance of email and you get back a null That would be an assertion failure that would be reported with an F for failure instead Of course writing that email class It's really simple that's what it could look like Really boring nothing to see there so now we get a dot in the output dot means successful tests and all tests are successful, so we don't get much more output and that is a Philosophy that PHP unit shares with all the other members of the X unit family of test frameworks Yes, there's this assumption that all tests should pass all the time and as long as that is the case Aside from some progress information while the tests are running and some summary at the end This is the amount of tests that I ran. This is the amount of assertions that were performed This is how much memory was consumed and this is how long it took You don't want any more information than that only when something goes wrong When you get an error or failure for instance, then you get detailed output about that specific test that failed or error out Normally you don't want To see output here for I don't know Imagine the Drupal test suite with several thousands of tests when you run them You don't want to see a list of the names of all these tests. You're not interested in that that would be a lot of output and in that Massive amount of output the information that you're really interested in would be lost Maybe 999 tests are successful and you'll see the information for that and somewhere in the middle There's the one test that is failing and you don't see that That's why when everything is fine. No additional output and that's our feedback loop We had we were in the process of writing something that captures an email address We use the test to describe how we want to interact with that email how that email could look like and Then we actually implemented that and that's a really nice feedback loop. It's called test-driven development test-driven development means the tests drive the development not as Not just for the sake of writing tests That's a nice side effect of test-driven development that you get the tests for me at least the most or one of What the most important thing about test-driven development is that it is a tool that helps me Think about the problem. It helps me understand the problem that I'm currently trying to solve and write Another test probably that that one uses probably probably the most common Assertion method that you use a third equals which compares to values Conventions are again are important. Of course for Comparing two values the order in which you compare them is not important if you come with compare a to be That's the same as compare comparing B to a The order, however, is important when the comparison fails and you want to provide a meaningful failure message That's where the convention comes into play The first argument is the value that you expect and the second value is the actual value that you want to verify and Match against the expected value so that PHP unit can tell you hey This test has failed. I expected this value I actually got this that does not match that is why the test has failed conventions oh Yeah, there's the output example. There's the f for failure. There was one failure. I Expected a string and I got an email object that doesn't match That is why the test has failed and then we can then we can implement the missing functionality In this case, we were missing the two string method that allows us to use the object as a string in a string context and then It just works what happens when something goes wrong, how can we test that in an error case of Indicates happens inside the code that we're testing How can we verify that we get an exception when that happens? that's How you test exceptions and Right before this presentation had a discussion with one of you from the audience about exactly this and the question was The documentation shows At least two different ways of testing exceptions, which is the one that I should use or which is That that we should use and As of right now That's the best practice or the good practice that I would recommend of using For a really long time until some point last year or One and a half years ago. I Recommended using the expected exception annotation Which at first glance is a lot more convenient. You put it in an annotation in a dog block in front of the test method It's not in the test code Some people prefer that some people find that easier on the eye easier to read There's one problem with that. There's at least one problem with that though If I put it at the annotate in on the annotation Then the test would be successful if at any point in the execution of the test method that exception is raised This allows me to tell PHP units Only after this point in time While running the test when I have this method call only now is it okay that this exception comes and that marks the test as Successful if that exception is raised before that expect exception call then it is an error and There were a lot of situations Where using the annotation hides problems in the code and That's one of the worst things that you can have when you're testing that you have a test that you went through the effort of writing the test Maybe even went through the effort of making the test the code testable that you're testing and Then have a test that lies to you because You get the exception way earlier and not in the place where you are expecting it And then it's hidden from you and the test tells you it's green. It's fine. Everything is good continue and it's not You don't want lying tests. That's what it looks like when it goes wrong We are missing what? more code we need to actually Have code in our email value object that verifies that this string that we pass is the valid email and Then our third test also works correctly So those were three examples for writing tests compared to variables for for equality using a certain equals Asserting that a variable contains an object of a certain type and ensuring that we get an exception when we want the code to raise an exception and Basically, I have shown you now all that you need to know to write tests for 70 to 80 percent of the cases PHP unit has a lot of functionality Just look at the documentation There are so many features. There are dozens of assertions dozens of configuration settings and Sometimes weird and bizarre modes of running the tests a Lot of those things a lot of those features were added over the course of the project because to support testing I Don't really want to say crappy code But code that was not written with testability in mind in a perfect world Which unfortunately we don't live in in the perfect world I could delete like 80 percent of the code and everything would be fine But It's this 10 20 percent that you need to know to get started and once you have mastered that then it's really easy to look Okay, now I am in this situation now. I need is a very specific assertion Look in the documentation. Oh, I find something. I need to assert that an array is empty and there's a certain empty And that's okay Maybe you are testing a piece of code that has a lot of interaction with global state It's manipulates a lot of global variables There's a feature that you can turn on that makes a backup of all global and super global variables before each test and Place that back after each test Don't turn that on if you don't need it if you write clean modern Object-oriented code you don't need global variables, so you can turn you don't Need to turn that on It's an expensive operation that takes time and consumes memory Don't do that But you can turn it on for the on a test-by-test basis for those tests where you need to Interact this global variables Maybe because you're testing a piece of code that is 10 15 years old and that still use those global variables and that's okay But to get the general idea of how to write and execute tests You don't need to care about that. You only need to know That's that's possible When you need it so all the tests that I've shown so far are unit tests and all of these Automated dynamic tests What they do is verification through execution. I execute a piece of code and I verify that it does What it is supposed to be doing or at least what I have understood what it should be doing Just because a unit test passes Does not necessarily mean that the feature that uses the unit of code that fit that we're using there That we're testing with the unit test Does what the user what the customer actually wanted? It's a different type of test that would that would be an acceptance test for instance You can write code that is really nice and clean and Modern and has good unit test coverage, but it still does not do what it is what is supposed to be doing Verifications through execution means I have a piece of code. I invoke it. I look at the result and make a decision Yes, this is what I want. This is not what I want There's a very special case Is regard to verifications through execution and That's a category of tests called characterization tests Those tests don't make a statement about whether or not a Software system or a part of a software system works correctly. It just captures how it works today Can give you an example from from a recent customer? They had a really large method four or five thousand lines of code By looking at it. It was not really clear What it was doing why it was doing it was doing a lot you looked at it and you could see okay It was doing four or five six different things Most of which were really important for at least one of those blocks the developers were not really sure whether that was really needed or Whether that related to a feature that you moved from the application three years ago And it was just a leftover We were not since we did not know what it was supposed to be doing He had a couple of arguments and we did not know with which arguments to call it and what the return value should be So we couldn't figure out Arguments to call it with and then an expected result And in a situation like that when you're writing tests for legacy code, that's okay That's where characterization tests can help So we looked at a couple of Requests to the actual site and figure out and got the information from from function traces With which parameters it actually gets called Right now in production and for these Sets of input What is the was what is the result and then we wrote some code a test an integration test that used that information and while we were doing that we realized hey it might be even a better idea to Just duplicate that method in the same class make a copy of that method and In our tests call it twice Call the the original one and called a copy and Then we made changes to that method we started refactoring it We sliced it down into five six smaller methods and we used that test Calling the old version and the new version and just compared The results from those two and as long as they were the same we were comfortable enough that we were not breaking anything that's the characterization test a very special case of verifications through execution You can Have a different perspective on verifications through execution when you Look at a test not only from the perspective of I Want to ensure that this thing works correctly. I'm and leave The view of testing and look at it from a different angle And then you can look at the test code that you wrote at the unit test that you wrote From the perspective of it being executable documentation a unit test is an example for how the unit that its tests can be used Imagine you are a new developer coming on the team That you that has somewhere in its code base this email object I had earlier and For the first time you need to work with that email object Sure thanks to naming, you know what email does but you don't know the implementation details of that and The promise of object oriented programming is that you don't even need to know The implementation details you only need to know the public API But still you need to know how to use that. So what do you do? You look at the unit tests for that email class and you see Actually working examples for how this code can be used Moreover, you see when I call it like this, then this is the result that I get That's perfect. That's really good if you shift your view on that test code slightly Then you go from executable documentation to executable specification Especially in the context of test-driven development the tests are a tool to structure your thoughts and understand the problem and then you use the tests to Specify how the thing that you are about to write should behave PHP unit supports this idea Through an alternative output That's called test docs and you can get that for instance using PHP unit dash dash test docs Then it just uses this alternative output and prints that to the command line. You can also get that as An almost nice looking at least it's not ugly looking html some teams Have really great six have really made a great Success and experience was using at html not to print it out Please don't hurt the trees but they use that in continuous integration and in addition to the normal output that is useful for the developers to generate this html and put it Somewhere on the internet on a wiki for instance and the domain experts the business analysts the non-technical Stakeholders look at this document and they understand that they see okay that the developer is talking about a concept that is called email And that can be created from a valid email address and and so on and that's something that I even as a non-technical person can understand And of course for something rather technical like email. That's rather boring It gets really interesting if you have things like contracts or Other things from your business domain represented as objects in your code plus the executable documentation and specification Through the tests and then you can take this show that to someone here This is how I understood that this piece of our business should work And this is how it currently works because this is automatically verified through tests Did I understand it correctly or not and this output? Believe it or not is a really good communication tool between technical and non-technical stakeholders of a project This Summarizes what I mentioned once or twice already at least for me Test-driven development and the writing of tests Unit tests especially is not just a broad verifying that something works correctly It is a tool that helps me think about the problem that I'm solving and as a developer my primary Job is not the production of code My job is to understand and solve a problem and yes sure as part of that I need to write code But the code is not really That what the user wants the user wants a solution Decades ago Bill Gates already said something similar when he said well The idea of paying software developers by the amount of code they produce is As silly as paying an engineer that create that builds an aircraft by the amount By the weight of the airplane. That's stupid. You want to solve a problem and you want a good solution And I can only give you my subjective personal experience I cannot work without Unit tests and in most situations I cannot work without test-driven development anymore I have still to figure out how to apply test-driven development to the development of a test framework Maybe at some point I figure that out, but when it comes to PHP unit I always write the tests after I implemented the feature test-driven development at least in most cases for the test framework itself doesn't work for me, but that's a Rather special problem that only people have that work on testing tools. So that should not concern you That's that's my headache not not yours But tests for me are a tool to to structure my thought process While I'm trying to solve a problem and that works for me rather well Yeah, and of course that somehow relates To what uncle Bob talks about or what uncle Bob means when he talks about clean code And to me still the best definition of what clean code is what what what we should strive for as programmers is What Dave Thomas wrote in the introduction? To the clean code book clean code can be read and enhanced by develop by a developer other than your original author I would even go further clean code is code that I can that I have written today and can understand a year from now Does not have to be another person It can be future you write code that future you and Your teammates today can understand Happened to me so often over this I don't know 16 17 years that I've been working on PHP unit that I needed to work On one area and I look at the code What was I thinking when I wrote this I don't understand it and look at the history. Oh, I wrote that 12 years ago Yeah, it turns out I learned something in the last five years and I wouldn't write the code like that anymore But now I have to deal with it and maybe rewrite it or improve it at least a little bit to make the pain go away Yeah, can be read and enhanced by a developer other than its original author It has unit and acceptance tests Meaningful names. Yes naming things is hard, but it's so worth it to have names That really reflects The domain in which your problem is Yeah, one way of doing things And not multiple ways minimal dependencies, which are explicit Meaning dependency injection make it dependencies explicit don't hide dependencies and make them exchangeable lose coupled code and minimal Yeah, and put in yet another way yet into another Phrasing what Steve Freeman and net price wrote in growing object-oriented software guided by tests the goose book For a class to be easy to unit test the class must have explicit dependencies that can be Substitutive and clear responsibilities that can easily be invoked and verified In other terms the code must be loosely coupled and cohease and highly cohesive or in yet another phrasing well designed and Test driven development helps you get there. I talked a lot about unit tests but there are other tests other kinds of software tests other kinds of tests that you can implement using a tool such as PHP units for instance and With all these tests there are a couple of questions that you can Use to categorize these tests What do I want to achieve with the test? What is it that I want to test? Do I want to verify that my software handles an Email address or a credit card number or an iBan or an address Correctly at a very low level. Yes. I want to verify that these things work isolated from everything else. I Do not want to test these things in the largest possible scope I do not want to have thousands of different tests that test with different combinations of credit cards and Credit card information and address information Using the real payment service provider whether or not that works or not That's not what you want to do That's what you want to do on the smallest possible scope because you need a lot of variance in there many different types of test make a lot of test data to exercise these really important pieces of code and If you do that with a unit test these tests are Really really fast and you don't need to talk to other systems and the much more robust robust and they give you precise information Sure, you will need a couple of tests that tests that exercise your entire payment process including talking to payment service providers But you only need very few of those you knew it basically just need to check Does it work for one address with one credit card and if it works for that then you can assume that it works for the rest Because all the variants you have tested on a much smaller scope. How much code do we need to execute? To verify the thing that we want to verify That's probably the most important question when it comes to testing. You always want to execute as few lines of code as possible the more code you execute the longer the test takes the more tech code you execute The more places you need to look for the cause when something fails If you only execute five lines of code as part of a unit test and The test fails then the reason for that test failing can only be in one of those five lines How do we write down the test? How do we formulate? The test impulse which basically means how do I write down how I build my environment? How do I invoke the piece of software that I want to test and how do I write down the expectation for this test? To be successful. There are many different ways I've shown you how to write down tests with PHP unit. There are other tools that allow you for instance to use natural language things like cucumber and be had which are well suited for large scope Acceptance kind of tests When do we write the test do I write a test after the fact do I do a test-driven development and write a test before? When do I execute the test a lot of tests make a lot of sense to execute in production? things like a B tests multivariate tests to test a hypothesis about a New feature does it make sense to implement that feature? Do I get better conversion if I make the button purple or blue things like that? You have to do and you have to test in production what you don't want to test in production is whether or not Your credit card validation works correctly. That would be rather stupid and if you Google or use your favorite search engine to Ask There's a thing called the internet for different categories of software tests. You most likely you will find one of many different pyramids Last time I checked there were like 15 different visualizations for software categories that use the pyramid Going to show you one pyramid That's rather representative of the others At the bottom you have Unit tests pure unit tests small tests Whatever you want to call them that only execute code from one unit of code in isolation from all of the dependencies Including not touching the file system not not not talking to the database not talking to the network in Some rare cases the object does not talk to other objects because it has no other dependencies It's rare, but it happens Most likely you have something on that level where you need to do where you need to use techniques such as stubs and mocks To decouple the unit of code that you're testing from its dependencies One level up you have integration tests Just because you test object a in isolation from its dependency b and be in isolation from a does not necessarily mean that a And be worked to correct it together That's what you do with integration tests Then you one level up you do edge-to-edge tests Which is as and to end as possible without using an a real HTTP client and a real HTTP server This is what you would do with a symphony application for instance where you instantiate the application inside the same PHP process that runs the PHP unit tests Say you you have a php unit test an integration test and you instantiate to Drupal and Prepare a request and give that request to Drupal and Drupal does its thing and gives you a response and you look into that response That would be an edge-to-edge tests It's a lot faster than using a real browser Instrumenting that sending a real HTTP request to the server and looking at the response Of course sometimes you need to do that especially if you have JavaScript in your front end and you need to test JavaScript interaction Then yeah, I'm already talking faster. My my clocks has one minute. Okay This is the last slide. I think So Of course if you have JavaScript and you need to do Something with JavaScript something like Selenium that instruments of Firefox the Chrome There's nothing you can do about that, but the pyramid doesn't stop there. You can go Even further up, but then you cannot automate it anymore Higher up would mean maybe you are an e-commerce and you want to test your Logistics tool chain and your warehouse What you can automate is go to the website search for a product go to the product detail page Put it into the shopping cart make a check out including a real payment and then have people in the warehouse Look at the people who work in the warehouse Do they take the shortest route to the shelf? Do they take the right kind of package? How long does that take and how long does it take for the? The delivery service to ring at your doorbell and deliver the package and yes People are doing that but no they're not doing that in continuous integration. They do that once a year So Almost on time sorry Thank you, I hope this was gave you an overview of what this PHP unit thing is about Hopefully in case you were scared of Writing tests and using PHP unit before hopefully you're not scared anymore Hopefully you're interested in trying this out And the last thing I'm going to say is I'm here at Drupal con tomorrow at the code sprint and Apparently I'm helping people Who work on tests for for Drupal core? But if you have a question about PHP unit be it related to Drupal or not feel free to grab me ask your question And I'm looking forward to discuss all things PHP and PHP unit with you tomorrow and help you make Drupal better. Thank you