 Yeah, okay. Good morning. Welcome to the first, to one of the first talks at work in Nuremberg. The first talk in English and the first talk on testing. I'm Torsten. I'm a workplace engineer at Insight and I'm filling around with Wordpress since nine years so far. So the title is how not to write testable code or how to write testable code. So the first question that comes to mind is what is testable code? Who here is a developer and wrote code? Who here wrote testable code? So every program is testable somehow because there are certain things that you can test depending on how you define testing. So if your function, your methods, your program, your piece of software returns a value. You can capture that and, yeah, compare to an expectation you had. If your code outputs some data, you can capture that and compare to what you expected. Maybe there are side effects. So you call a function and you know after that some variable, I don't know where it is, should be some value, should have some value. So there are side effects and you can raise expectations on other parts of what you actually called. Yeah, another test is your program doesn't crash but, yeah, that's not so good. So when talking about testable code, it's mostly, so what I'm referring to when calling test, when using the term testable code and mostly what you find online is code in the context of unit testing. So it's actually unit testable code. Okay, so what is unit testing then? That's also called components or module testing or other things like that. Unit testing in general is dynamic testing of individual units and these units are tested in isolation. So if I want to test one method, I only execute that method or the original code of that method and I want to test that. I don't want to call a method which again calls a method and then a method and I don't know if there is an error, yeah, is that error in my method that I actually called or somewhere in the call chain. The reason for testing are finding defects in software components. So if I test a method and I have an expectation how that should behave, what that should return or output, yeah, I can find defects if that does not what I expected to do. Unit testing is usually done by developers. So either exactly the person who wrote the piece of code is writing the unit test maybe even before the code itself or some other guy from the development team. Now let's have a look at dynamic testing. Unit testing is dynamic testing and dynamic testing means I have codes and I actually execute that. The other thing is static testing which is just reading the code, my tools read the code and yeah, there are some measurements syntax highlighting and stuff like that. Dynamic testing is executing the code. I want to verify my piece of software. I want to find failures that are the visible thing that is caused by a bug in my code. That's a failure. And of course there are different testing methods when doing unit testing. There are black box testing, white box testing and other things like that. When doing dynamic testing, black box and white box and unit testing is verification and it's mostly white box testing. So let's have a look at that. Verification that's definition of verification. What's important here is that we have conditions on our software and yeah, we want to check if these conditions are satisfied by the product we developed. So one claim here is are we building the product right? We have the wish lists of the client and we want to verify that the software does what is written in the wish list. White box testing is structure based testing. So I actually have the code at hand and I really examine closely my methods. Sometimes I check every single line of code and I do something to check that, set expectations or I build individual tests to make sure that every line is executed or whatever measure I'm following here. So I do have to have knowledge of internals of my code. Of course there are different white box testing techniques. Yeah, that's up to you for every test that you write. You have to decide what risks are here involved, how many tests, how much time do I have to spend or do I want to spend here. Yeah. Okay, let's come to some unit test examples. The first example is pretty simple. We have a class with one method. There are no external dependencies in my class and in my method. And so every or all that I have to use here is some unit testing framework. These are some testing frameworks that you might use for PHP and yeah, JavaScript testing frameworks over here. So that's the first example of our subject under test. So we have a class and we have one method and we want to test that method. Yeah. Calling that method returns the string 42. I do have knowledge of that code so I can read that code. And then I can write my test. I'm using PHP Unity here. This is a PHP example obviously. And I write one test method for my methods that I want to test which is get answer. So my test method is test get answer. I'm creating an object of the class where the method I want to test is in. Then I call that method which is in the third test to get answer. This is actually executing the method I want to test and I do have set an expectation that I want to make sure that the string 42 is what that method gives me. That's what that should return. This is the JavaScript version using the tape, the unit testing framework. Yeah, pretty likewise. Some little bit more complex example is I have a method and there are conditionals inside. I have an external dependency and maybe that's why I want to use a mocking framework. These are mocking frameworks for PHP and JavaScript. Here is our subject under test. So we have a constructor method and we inject an oracle object there. And yeah, maybe we spend enough money if we want to get the answer, then the oracle will actually return the answer. If not, I don't get an answer. And that's the test. I want to test the get answer method and not the get answer method of the fortune teller and not the get answer method of the oracle that's injected in there. So I create a mock and just say if the get answer method of the injected oracle object is called, it returns something. It doesn't matter what, but I know what that is. It's just a string answer. And then I call the method get answer of my fortune teller with enough money or the first time with not enough money and then with enough money and I have two expectations or two asserts here. That's the mock version. The first version was the PHP units built in mock builder and that's mockery. That's some mock framework to mock objects. It's pretty the same. That's the JavaScript version. I'm using sign in JS here to mock the object and yeah, the test structure is just like PHP. A third example is the same as one, but there's a WordPress hook or there's a WordPress action involved and there's a filter hook involved. Yeah, and that's why I'm using WordPress mocking framework. Brain monkey and WP mock are two mocking frameworks working specifically for WordPress, which you can use. That's the subject under test. So I'm firing an action when I call that methods and I'm returning a string that's passed or that's run through a filter. And I want to make sure that the stuff that's happening there actually happens like I wanted to be. And that's the test example. Here's the WP mock version. Okay, just examples what unit testing means. So let's come to bad practices now, but bad practices showing bad practices alone is not so good. So I'm also showing how to make them good. If that's the function, you can see on the top right corner of the code block what language that is. If that's not obvious, I'm switching between PHP and JavaScript. What's the problem with that function if I want to test that function? Any idea? Yeah, exactly. There's no feedback given. I call that function and I don't know if check something is returning true or false or if do something was called or not. So the solution to that is just give feedback. If you're early returning and you don't have return values in your function, just use Boolean return flag if the actual thing that you're expecting your methods to do is or was done or not. That depends actually on the context of your methods. Maybe there are certain early return statements. So maybe you want to return an integer and you have your mapping or you return some enumeration, just constants that are strings returning the integer. So you'll know, okay, I did not the thing that the method actually should do. I returned for that reason or that reason early. There's one thing that you have to consider. Maybe returning something has side effects. Two weeks ago, I refactored some JavaScript code and I thought that methods, there's an early return and I don't return something. So I just put in there return true and return false. The thing is that was a method attached to an event handler and returning false means yeah, prevent defaults. The event doesn't bubble up. So that's not what I wanted to do here. Okay, then I refactored that, of course. Second example, PHP code. What's the problem with that? That's the code that's actually being executed in my PHP process when running PHP unit. Yeah, that's exit call definitely means I'm terminating my PHP script execution. That means I'm terminating my PHP unit execution. So just delegate the exit call. Maybe it's better than after what? Yeah, if that's okay. If it's something that you actually really don't understand, then of course yes, but it's just out of interest. Yeah. So what you might do here is just, yeah, write a wrapper function for exit, which then you can mock. So you can mock your checker object where you want to test the check data methods and mock the call exit methods from there. So I could have made that public or protected if I'm just extending the checker class. And then the call exit method does nothing. Maybe it's returning exit the string or it's an outputting exit and then I can check that. But the actual PHP function exit is not being called in my test, but of course when I'm running my software just as it should be. So this call exit actually called the PHP language construct exit. This is some similar example in JavaScript. So maybe you want to process some data and then redirect the user to somewhere. The problem here is of course, yeah, you're actually being redirected and if there are several tests going after that you won't reach them. So the solution is just the same. You write another function which actually does the redirection and you call that method and you can overwrite your global, depends on where it has global dot set location or window dot set location and yeah, you can test process data without actually redirecting and yeah. PHP example again, what's the problem here or not the problem but what might be an issue here? Sorry, missing? Yeah, exactly. What I'm doing here is the render for method data method is actually just a wrapper for the methods on an object that I don't have already. So I create that and the problem is I actually execute the original, the real methods on that object. So I cannot mock that. What I could do is in my test outer loader just don't load the actual formatter class and provide some stub class. So I just include what, yeah, my tests or the things that I want to test are using and return some data that I just know. The easier example here is actually use dependency injection. The example here shows constructor injection. The advantage here is my constructor method is expecting a formatter object and I can mock that which just has some method format and that assures, yeah, maybe format or stuff like that. So my actual code if I want to execute that, I create a formatter object, I create a render object, pass the formatter object into that and in the tests I'm passing a mock object there. Okay, maybe this is sometimes true or it's the case. I don't, I don't know what I'm not in the position to create the object before creating, let's go back there, create the formatter object before creating the renderer object. That's because maybe the formatter object that here is being created or in the other example is created in the render formatted data method, maybe that depends on stuff like options or settings that are passed into our render formatted data. So maybe like that. I want to format data and there's the options array or options object or it's an options class or so, yeah, the solution here is use a factory. So there's no actual object instantiation here in my code because that's delegated or it's abstracted out into the factory which is again dependency injected in the constructors. So I can mock the factory here. That's returning some mock of my formatter object and everything's cool. And yeah, depending on what is in my options array, the factory returns other formatter objects. Okay, what's the problem here? Maybe the variable name already gives a hint on that. I want to test my some function method and I want to write a test and make sure that my tests every time I run that is actually passing. The problem here is global foo. Global foo is not a variable in my function scope. It's a global variable. And if I run my tests and it passes and then I run other tests and maybe one of these tests is fiddling with the global foo variable, then I run my, what's it called, some function method again and my test now fails. Why is that? That is because I have no absolute control over the whole environment, the whole context in which my test is running. So if I need global foo injected, now I have a local foo variable which is the value of the global foo if I inject that. But every time I actually call the function, I know, okay, I passed something in there and I had an expectation and that's wrong. So I definitely know local foo is not what I expected to be. And yeah, that's global foo I passed in there. Okay, so global foo may be changed since last time. Singletons, yeah, singletons are good, singletons are bad. That's a great debate. One thing that's true about singletons is I cannot easily test a singleton that has an inner state if I cannot reset that object. Because maybe I create my singleton, then do some things and the object has its inner state and then I do some methods and the test fails. The other time I do that method before the stuff I did in the first time before. So my singleton object has a different inner state. That's why, yeah, tests pass or fail. So what I want to make sure is that I create or reset an object. Absolutely like it is when it's created the first time. So the solution here is just at a reset method. And that either actually resets the inner state. So if I have some inner data object or data array or so, or it just resets the inner instance point of all reference. So actually if I call reset on my singleton and then I call get instance, I get a new instance because it's, yeah, the self instance variable is not set. So there's a new self created. What's the problem here or what might be the problem here or what's just a bit over complicated in that example? Yeah, exactly. I'm passing some objects and I don't use it. I use it but just to get another object and then I work with that. Who here heard before about the law of Demeter? The law of Demeter is some rule sets of what you, when you're inner methods should call or what methods of which objects you should call or should not call. So I have a method M of my object O, no matter what language, okay, object oriented of course. And my method M, in my method M should only call methods of the object it belongs to or any objects passed to M. So if I dependency inject stuff into my method M, of course I can call methods of things I pass in there. Any objects instantiated or created in my methods, that means just using the new keyword and PHP or creating objects via factory methods or factory objects, that's also okay. And properties of my object. So if my object has a property which is constructor injected of my class, of course I can use methods of my properties. So let's have a look again at the code from before. What I'm doing here is injecting some object, get another object and then get something of that object. So how is ID even being called is something like that maybe. I have a function or it's just a global scope. I have that sum object and I use this ID even. So this is what you could do and you actually pass the object that you use or that you need in your is ID even method. So I'm just using the sum object dot get other object in the function that calls the other function that actually only needs the other object. The problem here is I'm doing static methods. I'm calling static methods which is something that I can only mock if I mock the static class which I may not every time be able to do. So what I could do here is just wrap the static method. Actually I create a class that has a method which is just calling the static method of my static class and then I inject my checker object into the class of the object I have and then I can mock my checker object. The problem here is if I want to test get formatted data, my object might not be completely initialized because get formatted data is using the formator which is a variable of my object, a property which is not set by constructing the object but it's set by calling the set formator method. So calling get formatted data before setting my formator needs to do some error warning depending on my language and setting. So user constructor injection creates the object by inject the object by creating my object and then everything is cool because formator is here. The problem here is I'm creating intermediary objects. I'm passing in an ID which I only, okay I'm issuing it out too but what I actually want here is the post object. So why not get the post object outside and put it in and then I can access the title, the content and the ID which I had before but then I had to create or fetch the object myself and the method is called render and not fetch something and maybe render if you have that's what you expect to have. So, yeah, name your functions like you want them to do and make them do what you name them. Okay, the last example is evil expressions. I cannot actually test evil code and the reason in this simple and stupid example is I don't need that. I can write what I have in my evil just in plain PHP or JavaScript or so and yeah. Okay, this was the second last example. The last example is stuff like that is in WordPress core and the digits are maybe three, the numbers have three or four digits or so. This is just a method with insane complexity. The method is called process. What does that mean? It does really a lot of things here. So I do have a lot of conditions inside. I prepare something depending on types or having set some data or not. Then I'm actually processing and that's what the method is called process and then I'm post processing and doing stuff after having processed. So if you write modular code then your methods is named something and it does that. You can have a method process which includes pre-processing, post-processing and stuff like that but it should not do that itself. So in the first part I have a checker object which is a dependency and I pass some of the stuff I want to do in my process method to that dependency. Then I use a method of the object the method belongs to, the prepare method. The prepare method prepares the data and the process method just makes sure the data is prepared. Then I have the processing itself and I have preprocessing, post-processing. So what hopefully did we learn today? Unit testing means testing in isolation so actually testing one piece of code. It's a function or method usually. When you have dependencies, don't create them in the method itself, inject them. Create them outside your object and then inject the created object which means you can pass in mock objects. Yeah, keep away from global states and scope for WordPress that's too late now. Write modular code, split up what you want to do, name actually the functions and think about what they do. If you describe what a function does and use the word and, maybe sometimes, yeah, that's not a good naming, the function does not do one thing. It does at least two things. And yeah, pretty please, write testable code, think about how I should write this or that line of code to make a testable even if you don't yourself. Because writing testable code is not that hard. There are some things that you have to keep in mind. And okay, to be honest, not everything I presented here is actually untestable or hard to test. For actually most of the things I showed here, there are ways to test that. But that means that either your testing framework has stuff going on in the background to allow for that or you have to do some things like creating a stub class or something like that. But following these bad examples and how I showed to make them good is just writing plain, straightforward, easy to testable code no matter what testing framework you use, no matter what you have to do besides creating just my code and creating the tests in whatever order. And yeah, you're interested in further reading and some of the references for my talk, that's the list. The slides are already online because yes, we have 1130 passed, so PHP should check that, should be online. And I also have a repository on GitHub where you find the unit test examples that I showed completely documented and for the examples I showed the bad code in the repository itself and a pull request for every example I showed to make them good. So be sure to test or to review the repository itself and the pull request section. Thank you. Do we have any questions? The question is we had that piece of code and why is it returning something which is that better than the block before? That's right. The thing is depending on your method, that's a simple method. I do have only one condition on which I return early. If it's false, then I return early. If it's true, then I go on. But maybe your methods just have a lot of external or internal dependencies and different conditionals and just setting an expectation on I get returned the int one to zero minus one or so or a string or false or true is easier than creating spies for your methods. So a spy is just I'm creating a method that does what I tell it to do and I have some additional measurements. I can check if that's being called, maybe what is passed to it, maybe what does it return. That is a good idea and most of the time you have to do that. You have to use spies. You have to use mocks. But you could do that additionally or it's just the easier way to go here. Because yeah, I can check if some other methods or functions that might be called in my functions actually are being called. But I just really want to check if maybe do something, did do something or not. That sounds strange. Okay. Yeah. Yeah. That's true. But having small modular written codes than my black box and white box test is also small. So maybe if I change my implementation and my test actually depends on implementation details, yes, then I have to change my test, maybe. But if you don't completely rewrite, refactor your method, then it's just adding some additional function checking that an action is being called or fired or so. Yes, you're right. That's white box testing relies on the code, the implementation, every single piece of code, at least every single piece of code that I actually include in my test. But yeah, changing the methods should not be too much work for me when changing or to have that I have to change the test, the test method. Which one? The, yeah, the right code, the wrong code or this is, some object is a dependency injection container. Yes, why not inject some object into my constructor? Is there a reason or is there a case where you could not do that? Yeah. If it's a factory, then I'm creating in the background an object, and the law of Demeter says you can use methods of objects that you create directly or indirectly. So if I have my factory object, and of course if I do have the factory object and I use it, I use it for creating some other object, and I only want to have that object to work with it. So of course, using a factory to create an object and then not calling a method of the object or setting or something like that, that doesn't make sense. And that's the reason why that rule is in the rules of the law of Demeter. So I think what you want me to explain is that not every example that I showed makes sense in every context, of course. Yeah. I did not do that before. It's another kind of testing. So it's just, you can do unit testing in a browser, but you don't need to do that because everything your browser does, display or something like that, you can check in your tests just by executing the code. You don't have to have the browser doing something like that. That's more like integration system integration test or actually acceptance test and user testing. And it's definitely a thing that you should do some when. And browser testing is mostly not the job of the people that do unit testing. It's another department and, yeah, of course. So there's nothing wrong with that and you should do both. Yeah. Sorry? No. I don't have time to test every single piece of code and I don't have time to write for everything I do tests before the implementation. The thing is actually you have to know your risks, the risks that are involved in your class, in your method or in the whole project you're working. If there are high risks, maybe financially or if I'm in the automobile industry or so, then there are people and there are people's lives involved. So, yeah, maybe that's a thing of my software that I want to really test carefully. If I have time, I will do it and I make sure that in the conception phase, there is time scheduled for testing. Yeah, of course. Okay. Thank you for your time. Yeah? The thank you or the references? Okay. Thanks.