[0:01] [Music] [0:08] hi and welcome to the dutch php [0:10] conference [0:11] 2020 edition we're so glad that you've [0:14] chosen to be here with us today we hope [0:16] you find it a [0:17] valuable investment of your time we've [0:19] got a great speaker coming up for you [0:21] but [0:22] real quick i want to give a huge shout [0:24] out to my buddies at ibuildings for [0:26] putting on this conference all these [0:28] many years [0:28] i've been involved in this conference [0:30] since about 2007 when i spoke at the [0:33] one of the first ones and just [0:35] absolutely love it it's one of my [0:36] favorite php conferences [0:38] ever and one of the main reasons that [0:40] it's my favorite is that [0:42] i buildings puts on a great conference [0:45] so tom yoni and angela and all the [0:48] i-building staff [0:50] thank you all for all the hard work that [0:52] you've put into this [0:54] and now it is my great pleasure to [0:57] introduce to you one of the [0:58] my favorite people in the entire world [1:00] this is julie or miss juliet formless [1:02] and she's going to talk to us about my [1:04] top 10 php unit tips and tricks juliet [1:07] take it away [1:08] okay so my talk is about php units but [1:12] before we start i'm going to reiterate [1:13] what cal said [1:16] and that is if the slides are actually [1:18] moving forward [1:19] for some reason they're not ah here we [1:22] go [1:23] so there is a github repo where i have [1:26] all the code samples we're going to be [1:28] using in this in the slides [1:30] and if you want to follow along go to [1:33] that github repo and the commits [1:35] which i'm referencing is in the slides [1:38] will [1:39] line up with that git repo and you can [1:41] also use it obviously afterwards [1:43] to browse and see um yeah what we talked [1:46] about and then to take your [1:48] benefit from that also as cal said [1:52] please discuss it's like there's a [1:54] specific channel for this talk [1:56] if you want to be sure i see your [1:58] message please place it there [2:00] okay now to really get started [2:04] welcome i hope you all had a nice break [2:07] my name is juliet reindus former and [2:09] we're going to talk [2:10] through my top 10 php unit tips and [2:13] tricks [2:14] the first one being have tests [2:19] okay how many people are behind the [2:20] screen now with their hands [2:22] in their uh they're facing their hands [2:24] sinking like oh yes [2:26] yeah i know i ought to but i haven't [2:29] i see a few at least one hand going up [2:32] here how [2:33] are the responses in the chat [2:36] cal okay cal's not responding [2:40] okay i realize if you have a legacy code [2:44] base [2:45] it can be really really hard and really [2:47] daunting to get started [2:49] on creating unit tests for your code [2:52] base [2:53] do not get discouraged but start [2:56] somewhere [2:57] start small so the very basics to get [3:00] started [3:01] is to have the setup in place so to get [3:04] the setup in place [3:05] first we're going to adapt the composer [3:07] json [3:08] by adding php unit to it and then adding [3:12] an autoload def to make sure that the [3:14] test directory [3:16] will autoload as well in the dev setup [3:20] good once that's done we add a php unit [3:24] config [3:25] now what this does is it basically tells [3:28] php unit [3:29] i have a test suite named foe in [3:32] the particular directory called tests [3:35] every file which ends [3:37] with test.php will be a test file and [3:40] please execute the tests in that [3:42] now there's two more things i want to [3:44] draw your attention to [3:46] first phpunit.xml.dist [3:49] the file name there you can use the [3:51] filename phpunit.xml or phpunit.xml.list [3:56] i'd recommend for a project to always [3:58] use the dist file name [4:00] the reason for that is that people can [4:02] then use phpunit.xml if they have [4:04] something in their local environment [4:06] they need to [4:08] tweak or do have the conflict slightly [4:10] differently [4:11] and they can then use that file because [4:13] it will overrule the disk file [4:16] second thing if you only have [4:19] a basic project where there's no [4:21] specific environment set the setup to be [4:24] done [4:25] just add the fender load from composer [4:28] as your bootstrap [4:29] and things will work fine right [4:32] next up you can actually get this [4:36] generated [4:37] largely by php unit itself [4:41] using the generate configuration so [4:43] that's your basics [4:45] and then you need to start somewhere so [4:47] start small [4:48] find preferably a standalone function [4:51] somewhere [4:52] which will just be an easy starting [4:55] point [4:56] to get the first test in place i'm using [4:59] this function as an example [5:01] strip quotes basically this function [5:04] says [5:04] i'm getting a string i want to make sure [5:07] that any [5:07] surrounding quotes are stripped but only [5:10] if they are the same type of quote [5:12] and not if they're like somewhere within [5:14] the string [5:16] good so to set up that as a test i'm [5:20] going to create a class called [5:21] a food test where the function test [5:24] strip quotes [5:25] i'm gonna extend the php unit basic test [5:29] case [5:30] i'm gonna call my function and i'm gonna [5:33] assert [5:34] that the results should be the same as [5:37] the expected results text [5:40] your first test is in place having those [5:44] basics in place [5:45] makes it so that contributors know that [5:48] tests are welcome [5:50] the tests are desired it makes it so [5:53] it's [5:54] that the next person who looks at the [5:55] code base wants to contribute doesn't [5:57] know where to start [5:58] knows that okay contributing test would [6:00] be a good idea [6:01] and maybe i should [6:05] next use the right assertion [6:09] hp unit has a wealth of assertions [6:11] there's over a hundred [6:13] assertions at my last count in php unit [6:15] nine [6:16] and one of the most common things i come [6:19] across is [6:20] people not knowing the difference [6:22] between assert equals and the search say [6:25] remember strict comparisons yeah assert [6:29] equals [6:29] is your double is searched same is the [6:32] tripolis most of the time when people [6:35] want to use [6:36] cert equals they really want to use a [6:38] search same [6:39] because if you use strict comparisons in [6:41] your code [6:42] why not are why aren't you doing it in [6:44] your unit tests [6:48] there are a lot of assertions available [6:50] this is just an example of [6:53] not even the complete set of assertions [6:56] and as you may see in the slide [6:59] nearly every single assertion also has a [7:01] not variant [7:03] so assert not contained only or certain [7:06] not contained assert [7:07] not empty asserts not ishval [7:12] use the right assertion and i know [7:14] getting familiar with all these [7:16] assertions can be hard [7:18] so just have the manual open have the [7:20] php unit [7:21] manual open next to your code base [7:24] when you're creating your unit test and [7:26] just check if there's a [7:27] assertion available which does what you [7:30] need [7:31] the reason why using the surgeons from [7:33] php unit is [7:34] important is one it makes your tests way [7:37] more descriptive [7:38] two it will make your test code a lot [7:40] simpler because all [7:42] of all the things php units can do for [7:44] you which you don't have to do within [7:45] your own test code [7:47] and three it will generally use the [7:50] wealth of information and wealth of [7:52] knowledge from [7:53] other people around the world to make [7:54] those assertions better if they need to [7:55] be [7:57] right now if we look back at that first [8:02] test we wrote let's fix that yeah [8:05] so that assert equals should have been [8:07] an assert same because we do want to [8:09] make sure [8:10] it's actually a string called text and [8:14] that we don't get well an integer [8:17] which will evaluate to something [8:20] and and you know not type juggling [8:24] and everything to do with that if you [8:26] want to know more about that [8:27] go and watch the big y equal doesn't [8:29] equal quiz [8:31] right next up don't just test the happy [8:34] parts [8:35] particularly people will use test driven [8:38] development [8:40] often have a tendency to focus [8:44] more than anything on the happy path [8:46] does the function [8:47] do what i want it to do instead of also [8:51] testing but how does it handle [8:54] unexpected inputs [8:55] how does it be how does this function [8:58] behave [8:59] in an unexpected circumstances you may [9:02] envision that your code will only be [9:04] used by you [9:05] but you have no idea of the imagination [9:07] of other people [9:08] people will use your code in unexpected [9:10] ways [9:12] well unless it's a closed story in your [9:14] own company but generally speaking [9:16] if it's open source if the code is [9:19] available to the public in any way [9:21] people will use it in unexpected [9:23] manners so don't just test the happy [9:26] parts [9:27] so if i look at that example function [9:29] again let's add some more tests [9:32] let's uh first the test with some quotes [9:35] within the text where the quote should [9:37] not be removed and then an unexpected [9:40] input [9:40] false and we document here [9:44] that that returns an empty string it [9:46] doesn't return the original value [9:48] it returns an empty string so your test [9:51] not only tests your code but also [9:54] document the expected behavior [9:57] now to allow for testing the unhappy [10:00] part [10:01] there's two things you need to remember [10:04] do not use strict types in your [10:06] tests and do not use parameter type [10:08] declarations [10:09] in your tests please do use them in your [10:12] code [10:13] but don't use them in your test because [10:16] it will make [10:16] testing the unhappy part really [10:18] difficult because you're [10:20] the type juggling will happen in the [10:22] test before [10:24] the parameters will actually get to the [10:27] function [10:28] under test so [10:31] it just makes it impossible to test [10:33] those unexpected [10:35] cases and those uh yeah the unhappy part [10:38] the unexpected inputs [10:41] limit the assertions per test [10:44] now you saw me adding two more [10:46] assertions to that previous test [10:49] what would happen if one of those would [10:51] fail [10:53] okay uh in this case [10:56] well i know which one i felt because it [10:58] shows me [11:00] where the plus and the minus the actual [11:02] expected text [11:03] and what the actual result was however [11:06] what happens if [11:07] the result would be true or false value [11:11] if you have three assertions and they [11:12] all expect through a false [11:15] this is not helpful you don't know which [11:18] one of the three assertions has failed [11:21] now every single assertion in php [11:24] has an extra parameter and the parameter [11:28] is called message and if we take that [11:30] functions [11:31] i've had the test function we had here [11:34] we can add [11:35] that message parameter and just tell [11:38] phpunit this is the particular assertion [11:41] which [11:42] is failed you may think oh yeah but this [11:44] is extra work [11:46] imagine how much time you will save when [11:48] one of these tests will start failing [11:51] that's where it's to help you debug it's [11:54] to make your life easier when things go [11:56] wrong [11:57] so if you make it a habit to always have [12:00] to have message parameters [12:01] if you have multiple assertions in a [12:03] test it will just make your life easier [12:07] now if that's a true false fails now you [12:10] can [12:11] see that it gives me a description of [12:14] the test case [12:14] and i know exactly what test case has [12:17] failed [12:21] yeah multiple assertions in a test okay [12:25] in this case in my example i'm [12:28] basically asserting the same each time [12:31] with different input and different [12:32] expected output i'm using the same i'm [12:35] using the [12:36] code in that case it's better to use a [12:39] data provider and the data provider [12:41] works like this [12:43] we have the test method and we tell it [12:46] that we're going to use a data provider [12:48] and the name [12:49] of the function which will be [12:52] acting as a data provider then we [12:56] tell it which parameters to pass to the [12:59] test function [13:00] and we make sure those parameters are [13:02] used so we use [13:03] in for calling the the actual function [13:06] we use out as the expected [13:09] value in your data provider [13:12] for every single test case you want to [13:14] test you create [13:15] an array so you return an array of [13:18] arrays [13:19] where every sub-array has those [13:22] parameters you're going to pass to the [13:23] function [13:28] without a data provider if one of those [13:30] assertions we had before those three [13:33] would fail the test would stop [13:36] because it's failed already and the [13:39] other [13:41] the other assertions underneath the [13:43] filled assertion would just not be run [13:46] whatsoever [13:48] with a data provider all three will run [13:51] it will just mark the one which failed [13:53] as failed [13:54] but the other test cases will still be [13:56] run [13:57] so it makes your test more descriptive [14:00] again and more stable [14:03] and now okay this one should be obvious [14:06] don't use your [14:07] own code to create test data [14:12] i know it should be obvious but it isn't [14:14] always obvious to everyone [14:16] and i'm going to read the account a [14:18] little anecdotes with permission [14:21] i was working with a customer on getting [14:23] their first unit test set up [14:26] and we discussed what we were going to [14:28] do we discussed the function we were [14:30] going to use it was a very [14:32] very simple function which was [14:35] translating [14:35] fancy phone numbers so 800 call now [14:39] to the real phone number [14:43] so we discussed using data providers i [14:46] asked the customer please [14:47] set up some test data create you know [14:50] some [14:51] inputs you want to use and some outputs [14:54] in the meantime i was setting up the [14:55] configuration [14:56] 10 minutes later i go and check with my [14:59] customer how he's doing [15:01] and yeah [15:04] what i saw him do is he copied and [15:06] pasted [15:07] his own code into evol [15:11] was running his own function in e file [15:15] with various inputs and using the [15:17] outputs from that as the expected data [15:22] the function was buggy if i would have [15:25] allowed that to continue [15:29] he would have what the test would have [15:31] achieved would have been to perpetuate [15:33] the existing bugs [15:37] instead always use an external data [15:40] source or [15:41] just your own brain which is also an [15:43] external data source [15:44] to create your test data if it's really [15:47] complex like a really complex [15:48] mathematical [15:49] formula fine use an external [15:53] site which also does that calculation [15:55] preferably use [15:56] two verify that both return the same [16:00] output and then use that for your data [16:02] provider input [16:04] do not use your own code to create test [16:06] data [16:10] name your test cases now [16:14] remember those test cases are created in [16:16] the data provider [16:18] if i use a feature which i really really [16:20] like called test docs [16:23] i can actually see which tests are being [16:25] run in this case [16:27] the test trick votes with dataset 0 1 [16:30] 2. now you don't want to do this when [16:32] you run a large [16:33] test suite but if you're debugging a [16:35] particular test class [16:37] this is really useful because you know [16:38] exactly where something is going wrong [16:40] you can see it go running but [16:44] what if i had 70 test cases [16:49] then okay test number 53 has [16:52] failed okay i have to go to the data [16:55] provider and start counting [16:57] to figure out which one is data set 53 [17:01] that's going to cost me a lot of time [17:03] again there's a smart solution for that [17:05] and that's called [17:06] named test cases so in your data [17:09] provider [17:11] when you have those arrays of arrays you [17:13] can use [17:14] the key and the key can describe what [17:17] you're testing [17:18] there and if you do that first of all [17:21] your tests become more descriptive [17:23] if you look back on your own test suite [17:25] in two years time you will know why you [17:27] added that particular test case [17:29] it makes your life easier in that sense [17:31] but also when a test [17:33] fails it will show you in a lot more [17:35] descriptive way [17:36] what has failed [17:40] see cal how are the people responding so [17:44] far is there [17:46] any questions so far hell [17:51] there are no questions in the q a and [17:53] juliet [17:54] okay thank you joni moving on [17:58] explore filtering now php unit has [18:01] an incredibly powerful filtering [18:04] mechanism [18:05] and quite often uh obviously in your ci [18:08] you're running your complete test suite [18:09] but when you're developing locally you [18:12] don't always want to have to run your [18:14] complete test suite [18:15] if you have 5000 tests and you're [18:18] just tinkering with one test class you [18:20] just want to run those tests [18:22] because all the others won't have [18:23] changed [18:25] so using filtering you can do that [18:28] and you can filter on a lot of things [18:30] you can filter on the namespace on the [18:31] class on the method name [18:33] you can even filter on the test case [18:36] number from a data provider or the name [18:38] from a data provider [18:40] and if this wasn't enough there's [18:43] shortcuts to help you there as well to [18:45] make it [18:46] still simpler it will take a little [18:50] getting used to [18:51] uh figuring out what will work and what [18:54] isn't uh won't work [18:55] basically it's being used as a regex [18:57] it's case insensitive [18:59] and as i said before incredibly powerful [19:02] especially in [19:04] the current versions of php unit it's [19:06] come a long way since [19:08] php unit 45 where the filter mechanism [19:11] wasn't as powerful [19:12] as it is now so if i just wanted to run [19:16] a few test cases i could filter [19:20] not string input on the previous example [19:24] and it will just show me the not string [19:25] input test cases [19:28] i hope you find this useful [19:33] don't trust test of a code coverage but [19:36] do examine it [19:38] okay now code coverage can be a hotly [19:41] debated topic [19:43] some people will say you have to have [19:44] 100 code coverage some people say [19:48] i don't care about code coverage at all [19:52] i'm somewhere in the middle but let's [19:53] look at that function we [19:55] used as an example if i have [19:59] one test case this function will be 100 [20:02] covered [20:05] however the regex adds an extra layer of [20:08] complexity [20:10] and even though the test coverage will [20:12] say this test [20:14] is a dysfunction is 100 covered in [20:16] reality it's not [20:18] not until i add a significant number of [20:21] extra test cases [20:24] now using test coverage [20:27] is a good idea do not hang yourself with [20:30] it do not make it a hard requirement [20:33] but do examine it do keep track of [20:35] what's going on [20:36] and okay some lines aren't covered [20:38] because they're [20:39] for edge cases and edge cases which are [20:42] so rare it's even [20:43] difficult to write a unit test for it [20:46] that's fine [20:47] sometimes you might have private methods [20:49] which you think uh [20:51] hang on but those are implementation [20:53] details so i'm not testing those because [20:55] i'm testing them via [20:57] other methods that's fine but do do [21:00] something with [21:01] code coverage do examine it to do so [21:04] you need to tell psp unit how to record [21:06] it [21:07] so first of all we're going to add a [21:09] filter [21:11] element to the config with a white list [21:14] and tell php units that [21:17] all our source files are in the source [21:19] directory [21:20] and that is the code which needs to be [21:22] covered [21:24] then we're also going to tell php unit [21:27] to lock the results [21:28] and i'm giving as an example the clover [21:32] logging mechanism the reason for that is [21:35] that a lot of automated [21:37] tooling which will integrate with your [21:38] ci [21:40] which you can use as status checks on [21:42] github [21:43] will use the clover file [21:46] now before you say help whitelist [21:50] each unit just like a lot of companies [21:53] and a lot of projects in the industry [21:55] is changing away from the term whitelist [21:59] as of php unit 9.3 that term is [22:02] deprecated and all these kind of [22:05] configurations are deprecated and [22:07] changing more [22:09] because they're now changing the basic [22:11] config [22:12] expects all of the whitelist code to be [22:16] terminology to be removed in php unit [22:18] 10. [22:20] if you want to have a preview look of [22:22] what the configuration will look like [22:25] once you move up to php unit 9.3 [22:28] there's a special sorry i'm skipping [22:31] something [22:32] there's a special branch in the demo [22:34] code repo [22:36] which you can see the commit which would [22:38] update this configuration [22:40] now the two things are skipped first [22:43] force covers [22:44] annotation okay this is about [22:47] accidental code coverage and intentional [22:50] code coverage [22:51] every test method should say i'm testing [22:55] this particular method or this [22:56] particular class [22:58] if you don't do that then a test which [23:02] doesn't have a cover stack [23:04] will just record any coverage on [23:08] any method it uses so that would be [23:12] accidental coverage where you're not [23:14] targetedly testing a particular method [23:18] by using the force covers annotation you [23:21] make sure that [23:22] every test has to have a cover stack and [23:25] codes [23:25] coverage will not be recorded unless [23:28] there is a cover stack [23:30] for those methods which don't [23:32] particularly test anything but you still [23:34] need that test [23:35] you can use covers nothing uh [23:39] be strict about co covers annotations [23:42] i'm a bit in doubt in two minds about [23:45] that one that [23:46] is very strict it basically says that [23:50] every single method even the ones which [23:52] you're using under [23:53] the hood including the ones possibly [23:56] from dependencies [23:58] would need to be annotated in a cover [24:00] stack [24:01] if you're very strict then yeah you can [24:05] play with it but for most projects it's [24:08] going a bit far [24:10] so know that it's there but make up your [24:13] own mind whether you want to use it [24:15] so if we go back to the test method we [24:17] had before [24:20] we're going to add the cover stack which [24:22] clearly indicates which method is being [24:24] covered [24:25] and in case you're now saying hey why [24:27] are you using an fqn [24:28] phpunit demands you use in fqn [24:32] you need to have a fully qualified class [24:34] name [24:35] function name not doing so [24:38] will not record the coverage properly [24:41] so even though you say yeah i've got you [24:43] statements no [24:45] fully qualified name please then [24:48] makes life easy on your contributors [24:51] whether it's your own team or a [24:53] team of open source contributors you [24:55] want them to use it correctly and you [24:57] want to [24:58] make it easy for them to run your test [25:00] but also run the test with code coverage [25:02] now once you've added the coverage tags [25:04] and add the logging [25:06] php unit will run with code coverage [25:08] every single time [25:10] and that slows down your test suite [25:12] incredibly [25:13] so to make it easier [25:16] add these two scripts to your composer [25:19] file [25:20] test with no code coverage as the [25:23] default [25:24] and then coverage which will record code [25:26] coverage [25:28] and to make life even even easier [25:30] sometimes you're just testing something [25:31] locally and [25:33] you don't really want to wait for [25:35] something to become a pr [25:36] to have some idea of whether whether [25:39] your changes are going to affect code [25:41] coverage [25:42] so make it easy to run code coverage [25:45] and create the result locally if you [25:48] create this script with coverage html [25:52] php unit will generate a website which [25:55] you can just [25:56] open in any browser and it will show you [25:59] the code coverage for your code [26:04] i hope everyone by now has heard at [26:06] least one thing which was new to them [26:10] but if not we're not finished yet so [26:12] don't leave without saying goodbye [26:15] sometimes you have tests which are [26:18] either [26:19] uh you either you're skipping them [26:21] because they're conditional like [26:23] they will only run when a certain [26:24] extension is available [26:26] or they will should only be run on a [26:29] certain php version [26:30] or you might have test stops where [26:34] you're [26:34] basically just go skeleton method [26:38] we need a test here but it's not there [26:40] yet [26:41] an incomplete test now [26:44] for a conditional test you can do it [26:47] like this you can just have [26:49] a comparison and return before doing an [26:52] assertion [26:55] that test will be marked as risky by php [26:58] unit because it's a test without [26:59] assertion [27:00] if you run it on php 72 we can do better [27:07] we can actually tell phpunit to mark the [27:10] test as skipped [27:11] then in that little dot overview which [27:13] you have as the default [27:15] test runner you'll get an s that test is [27:18] skipped [27:19] but then you still don't know why the [27:22] test is skipped [27:23] so document that by adding a message [27:26] this test requires php 73 [27:30] and the example code is in in the test [27:33] branch [27:35] is a bit nonsense but it's just to drive [27:37] the point home [27:38] what the different options are in this [27:40] case if [27:41] we now run the test again we get the s [27:44] for skipped [27:45] but if we run php unit in for bose mode [27:48] it will also list [27:49] all the skip tests including the reason [27:52] they were skipped [27:54] now psp unit has a number of built-in [27:58] checks there so for php version or a pc [28:03] unit version or an extension or a class [28:05] exist or function exist [28:07] you can actually use annotations [28:10] and it will do the same thing and you [28:11] don't even have to do the version [28:12] compare yourself anymore [28:15] and again php unit will [28:19] annotate that with information and mode [28:21] with why the test was skipped [28:26] right now and one where when i [28:29] previously gave this test i got [28:31] responses on twitter from people seeing [28:32] the slide saying like i've now made my [28:34] test [28:35] cross version compatible [28:40] sometimes when you have a project you [28:42] can determine freely what the minimum [28:44] php version is [28:45] and you can say okay seven two seven [28:47] three [28:48] fine however especially with open source [28:52] or [28:53] with projects which work with legacy [28:55] code [28:56] so upgrading might be difficult and [28:59] changing the minimum required version [29:01] might be a slow process [29:05] if we look at the versions of php unit [29:07] itself [29:08] you can see that of the currently [29:11] supported versions [29:13] uh which are php unit eight and nine [29:16] php seven two sorry [29:20] my clicker is gone php72 is the minimum [29:24] uh and with php 7.2 as a minimum [29:29] yeah if you still need to be uh support [29:31] php 7 [29:33] that's going to be difficult because [29:37] in php unit 8 php unit [29:40] introduced void return type for any of [29:43] the fixtures [29:45] and by the fixtures i mean things like [29:48] uh you use this particular type of [29:51] functions called [29:52] setup before class tear down after class [29:54] setup [29:55] and a teardown set before class and ah [29:58] tier that after class are [29:59] for setting up things which are used by [30:01] every single tester [30:03] and setup and teardown are run before [30:06] and efforts [30:07] and after every single test [30:10] with the void return type dead void [30:12] return type wasn't introduced until php [30:15] 7-1 so if you still need to support php [30:18] 7-0 and therefore also need to support [30:21] php [30:22] unit 6 you have a problem [30:25] and i'm going to click through to the [30:27] next slide and look if i can find [30:29] a little bit from to get my clicker [30:32] working in [30:33] i don't think i can so in the meantime [30:36] let's have a look how we can do this [30:39] as of php unit 8 we need the void return [30:42] type [30:44] this is a problem so what to do to get [30:47] rounded first we rename the [30:49] method [30:52] to setup database connection because [30:55] that's what it does [30:56] it makes the method far more descriptive [30:59] than setup before class anyway [31:01] and we add the before class annotation [31:05] with the before class annotation it will [31:08] run the method as if it was set up [31:10] before class [31:11] and you do not have to have the return [31:13] type for it [31:14] same goes for after you can use [31:17] after class rename the method don't use [31:20] the return type for it [31:22] and similar for setup and for teardown [31:25] which are the methods [31:26] run before and after every test again [31:29] you have the before [31:30] and after annotation you've seen me use [31:34] several annotations now you've seen me [31:36] use [31:36] annotations for coverage you've seen me [31:39] use these annotations you've seen me use [31:41] the requires annotation [31:42] there are more please have a good look [31:45] at those [31:46] because annotations can be really [31:47] powerful in php units [31:49] and before you ask yes [31:53] these annotations before class after [31:55] class before and after [31:57] will stay supported at least for the [31:59] foreseeable future [32:01] i spoke with sebastian and he's [32:03] indicated he has no intention [32:05] in the foreseeable future to drop [32:07] support for them so this should make [32:09] your [32:09] test suite cross-version compatible with [32:12] various php unit versions [32:14] and still maintainable for the future [32:19] okay test your tests now this might [32:22] sound [32:23] really really matter and in a way it is [32:26] but are your tests actually testing what [32:29] they're supposed to do [32:31] to test what are they stable what if [32:34] something changes in your code base will [32:35] you start a test start failing [32:37] uh straight away and [32:40] in some cases will they not fill when [32:43] it's something like a constant which [32:45] change [32:47] should the test maybe take that constant [32:48] into account [32:50] so to help with that first of all [32:53] we have infection infection is mutation [32:57] testing [32:57] it's a framework which will try [33:00] to mutate your source code and then [33:05] see if your tests fill correctly on the [33:07] mutated code [33:10] if you want to learn more about it first [33:11] of all there's a url to their own [33:13] website but second of all [33:15] there's a youtube video from my dear [33:17] friend michelangelo van damme [33:19] where he gives a little demo of how [33:20] infection works [33:22] i'd recommend watching it and i know [33:24] he's given more talks on it if you [33:26] have a chance to see it uh go and watch [33:29] michelangelo from them talk about the [33:30] election it's worth your time [33:33] another thing and this is just a quick [33:35] refill because they're not [33:36] online yet php unit compatibility and [33:40] php unit qa [33:42] these will be rule sets for php code [33:44] sniff so they will integrate [33:46] in your coding standard check which you [33:48] do by default anyway [33:50] don't you and [33:54] these will the qa one will check things [33:57] like [33:58] hey you should use a different assertion [34:00] or there's a more specific assertion you [34:02] could use for this particular [34:03] test code php unit compatibility will [34:06] warn you just like php unit itself does [34:09] in verbose mode [34:11] about using certain things which are [34:13] deprecated [34:14] except php unit will do it when you're [34:18] basically already [34:19] too late and with this you can do it [34:22] using an [34:22] or an older php version to figure out [34:25] what is needed to upgrade [34:27] your test suite so expect those soon [34:33] last tip lose count [34:37] i think i said at the beginning this was [34:38] a top 10. [34:40] please follow example lose count [34:43] you can never have enough tests having [34:46] some extra tests even though the really [34:48] edge cases and you think those will [34:50] never ever happen in real life can be [34:53] helpful [34:54] uh also remember things change [34:58] in the world whether it's in your [34:59] dependency or whether [35:01] php8 which is around the corner comes [35:04] along [35:05] and changes all sorts of notices and [35:07] warnings to [35:08] errors and exceptions make sure you test [35:12] those edge cases [35:14] because then your test suite will be [35:15] able to catch those situations [35:18] of php cross-version compatibility or [35:20] changes in your dependency [35:22] before it gets to production so it's not [35:25] a bad thing to have some extra [35:27] test cases right [35:30] that was it for me i hope you enjoyed [35:33] this talk i hope you found something [35:35] useful in it [35:36] please leave feedback joined in you can [35:39] use qr code on the slide [35:41] to get straight to the right page the [35:44] slide will be up later this afternoon at [35:46] speaker deck [35:47] and yeah of course [35:51] read the docs from phpunit [35:54] cal are you there now yes you're there [35:59] and we have a question please [36:02] um about the usage of code to generate [36:05] test data what is your opinion on using [36:07] constants from the code on test [36:14] come again about the usage of [36:18] code to generate test data what is your [36:21] opinion on using constants from the code [36:24] on tests [36:25] i tend to duplicate the constants in the [36:27] test to ensure the changes in the [36:29] constant values are detected [36:31] but some colleagues disagree with this [36:34] okay it depends on the context and i [36:38] can't give you [36:39] a hundred percent answer because it [36:41] really depends on the code [36:42] there are in my own code basis [36:46] i have situations where i'm [36:49] duplicating the constants just to make [36:52] sure that if the constant [36:54] changes the test will fill and i know [36:56] something has changed [36:58] uh there's also places where i use the [37:02] actual constant from the source code [37:05] because it's a public constant in this [37:07] case [37:08] in my test to make sure that the test [37:12] will [37:12] continue to pass even when the constant [37:15] changes [37:16] so it depends on the context and you [37:19] really need to look at the individual [37:20] situation for that [37:23] excellent i know it's not yeah it's it's [37:25] not a yes or no answer i'm sorry [37:30] that's okay it was an answer so hey [37:33] um let's see i think that's the only [37:36] question we had for you [37:37] so i am going to thank you for that i [37:41] appreciate that that was a wonderful [37:43] presentation hope everybody got as much [37:45] out of it as i did [37:46] okay um let's see let me [37:50] take back over the screen and share that [37:55] okay we got 20 minutes until the next [37:57] talk 20 minutes so get up get stretch [38:00] get you a cup or a glass of whatever [38:03] you're drinking for the afternoon [38:05] and we'll be back at the top of the hour [38:07] hey don't forget go out to joined in [38:09] leave juliet some feedback on what she [38:11] did right and what she can do better [38:14] and of course we always appreciate it [38:15] when you tweet out [38:17] or whatever social media you use when [38:19] you post about [38:20] dpc20 thank you we'll be back in 20 [38:23] minutes [38:24] see you later [38:34] you