 Rhaid i'tio hun wedi digwydd. Rhaid i'r bwysig. Nid o ddododd rheu hyfforddiadau yn Arhefgrifol Gwerthoedd. Arhefgrifol Gwerthoedd arfer yn gweithio roi cael gweithio unig a ffwrdd ni'n... ..o arherwydd ar arherfaf Gwerthoedd. Roedden ni'n bod yna'n addyn nhad i'r fforydd... ..gyrchu ei ddweud y rhanonod mewn ffwyrdd ychydig... ...yna'n teimlo ychydig ac yn bwysig yn ei ddarw'r gwahanol. Wedyn heb ben i'ch gweithio cadwydderu ac yn modd yn dod y cyfanc mewn gweithio'r wych. A dwrd wedi'u gwneud y llygiad, eto'r cyffredin yw'r ystafell, byddwn i'r amlwgr i'n gweithio i gweithio'r amlwgr y drefwnr yfa'r blynyddio'r ffór gweithio'r gweithio'r ffór gweithio'r gweithio. Rwy'n gobeithio ei fawr deilig o gweithio'r bethau dydyn nhw a gweithio'r ideaeth, how features work, so how it burns the injection sort of works. But a very quick reminder of that. So a fixture is basically so any test function can request a fixture by just taking a parameter, a named parameter, and the named parameter will then be looked up by two function that's decorated with this fixture marker, which is just a function with terms of value, and that value is then injected by prior testing to your test function. You can create fixtures on different levels in your files. So if you do it in a class, it will only be visible to members of the class. So that's sort of very quickly the basics. So the first thing to start sort of extending that is caching a few fixtures. This sort of... So basically by simply giving another keyword argument to this pie-tester fixture decorator, you can change the lifetime of how long that fixture lives. Normally it's being... If you don't provide an explicit scope, it will just be torn down straight away after the test function has run. But you can change the scopes into session scope. You also got module scope and class scope, as well as function scope. And that basically means that you'll only call that function once for the scope. So in this example, we got two differently scoped ones, one function scoped, one session scope. And we got two tests using both of these. This is fairly contrived, I guess. But if you run a pie-tester in the output, I'm using minus s here, which kind of stops the... Make sure that the print statements I put in my test code actually get shown up, because normally pie-tests will capture that and only show it in the case of failures. But with minus s, you can clearly see the order that things happen here. So the session setup happens first, and then the function setup happens then the dot, which is basically the test that's been run. And then the function finalises it there down, kind of happens, and then that happens again. So you can see how the caching sort of works there. So if you've got expensive fixtures that you don't want to recreate the whole time, like populated database with schema or something, or create web browsers, or those sort of things, this is a very common thing to start kind of using. Yeah, and you have sort of available scopes there. Next on, you can sort of... Fixtures can just... Can be used in other fixtures as well, not just in test functions. And that makes it really composable, because it means you can have a... So in this example, creating a database connection fixture, and that might be used in some tests directly. But then, for example, if this was a functional test and one functional test needed a table to be there or something, I can just build on those existing fixtures and you can puzzle them together in that manner. One of the things here, the request fixture that's being asked there, is it's the way to out-finalise us to places. So you've probably already seen that, but it's essentially no more than just another fixture in pilot tests. It's just a build-in one that's provided. So that kind of happens quite seamlessly. The test function here simply uses the latest one, the DB table fixture, but it could have been using both as well. So if it needed both of them for some reason, there's no reason not to combine it that way either. Another thing you can do in fixtures is... Normally, when you're on test, in pilot tests, you can mark testers, so I want to skip this test or something for whatever reason. But you can also do it as based on triggers from inside a fixture, basically. And if you do it out, it means that any test that will be using that fixture will automatically be skipped instead of... So you can make this depend on something else. So this example is something that we use quite commonly when we connect to a remote service sort of thing. So basically, first try if the developers are running it on their own local host, if not, see if they're in the office, try connecting to the server on that network sort of thing. But if NIDR is there, then whatever, let's go and skip it. And combining this with the session scope, for example, means that you don't keep doing that again and again because that might be slow operation or something. Another thing to note here is that when you call pi test.skip like this with a message, it's basically pi test.skip will raise an exception in your code. So for the control flow of your fixture, you have to realise when you execute pi test.skip. You're basically raising an exception in there and pi test will interpret that as, but no code will be executed afterwards anymore. Just like you got pi test.skip, there's a pi test.fail. Will do exactly the same, but failure test for whatever reason, if you want to do that. And this is sort of a slight sidestep talking about introducing marks a little bit. Hopefully you've already encountered marks, but pi test has very flexible marking systems. So it's basically just a decorator, pi test.mark. And then a name you choose yourself sort of thing. And you can just apply that decorator to your test functions and then your test functions will be marked. That on its own doesn't provide you very much. You can sort of use that on the command line to select your marks, but it doesn't provide you that much yet. I'll get back to that on the next slide, basically. But one thing to note here is that you can mark multiple marks. You can obviously apply multiple marks onto your single test function or anything like that. But another thing is that because marks are so flexible, they're allowed to be made available on the fly, basically. And one sort of sidestep, side effect of that is that if you make a typo in a marker, you may not notice that and that may kind of hurt you later on. And that's why you sort of have two camps of people, I think. Some people, like me, prefer to use the minus, minus strict option to pi the test so that you get caught out and you have to basically declare your markers up front and you get notified of any mistakes you're doing. And the obvious way to just always enforce that is to write it in your configuration file. So that's basically the example of how you write it in your configuration file. Adopt basically always adds the command line option when you invoke it and then you declare your markers. In this example now, if you tried to run this, it would fail because only one of the markers has been declared. So that's sort of markers, but the... So markers are like, you know, you use by-plugins, et cetera, as well, if you've used plugins. They often make use of that. And one way to make use of that is inside, basically, detect them in your fixtures. So in here, the test function wants a Mongo client. It's a little bit contrived because pi Mongo doesn't quite work like that, but almost. But so basically it needs a Mongo client. And we're also declaring, basically, the marker is basically declaring the database to put in the URI to be used at connection time. And then when you actually look in the fixture, you can basically what it tries to do is like, it tries to look, is there a marker? Yes, then I'm going to use that as the database name if not, I'm just going to use a default database name and then create the client and return it. And to actually get this marker information, you use request.node. So request.node itself is basically the test node which is a internal part of the test representation of your test itself. So one of the attributes will actually be the function that you're actually testing. And it has quite a few methods. I think you can look it up in the documentation, at least part of them are documented. But getMarker is basically how you get a whole of a marker. The only thing is like, you then basically get this sort of marker object and in the case, so either you get this marker object or none, if you get none, we just use the default one here. But in the case of a marker object, the way it passes, because as you see the mark takes an argument here and the way it passes on the arguments that you've specified, it just passes these on as this arcs and Kw arcs attributes on your marker object, which is a list and a dictionary, which is a very common representation. But the problem with that is that it's not how Python signatures sort of work. So I use this little helper function which is like a call API phone in this case. It doesn't do anything useful other than it uses Python itself to pass a signature for me. So it means that if someone, if I wrote the decorator here differently, MongoDB equals uses, it would still work because Python would just pass a signature and return my database back. So that's how I call that function with star arcs and Kw arcs. So that's sort of a little trick to get native Python signatures working there. I have to add that in the future that, I think probably one of the next releases, that there is going to be a slightly different way or a new way introduced of declaring markers which will get around this little hacky signature passing stuff. So that will improve, but this is sort of the way we do things currently and it works very nicely. So another commonly used thing is fixtures can also be automatically used basically. So normally fixtures are always dependency injected. So your test function requests the fixture by name it wants to have. But sometimes that might not be suitable. So there's this auto use equals true argument to the fixture decorator. And in that case, it will basically be called for every test function automatically whether it's been requested or not. So this is kind of a lot closer if you're used to the unit test kind of way of things to set up and tear down because that's just called every single time. One of the nice things here is as well that you can combine this with the scope argument as well. So if you create an auto use fixture with a scope of the session, that basically means you only actually write the beginning of your test session, you'll be doing set up and at the end you'll be doing some tear down. The auto use fixtures, in this case, I sort of use it with an underscore so it's sort of indicating that I don't expect it to be used immediately or directly. But there's nothing stopping you from, there's nothing stopping you from returning a value as well and explicitly requesting it. So if someone explicitly requests it, you can just mix those two together as well. So in this case, it's sort of usually to create this kind of custom skipping logic for something that's only supposed to work on Linux. There's various ways of doing that, I guess, but it's an example. Then parameterising fixtures is sort of another very powerful feature that you can do with fixtures. So in this example, we have a test function, the first test function, TXN, which just uses basically a URI to connect to a database and say, the problem here is I want to ensure that whatever this works with PostgreSQL Oracle and SQLite, for example, at the same time. So instead of having to write three tests or write tests with different fixtures or something, you can basically parameterise your fixture itself. So by parameterising this fixture, Pyder test will create, will call my test function three times once with each parameter and the way you know which parameter, so the arguments in the list to the parameters keyword in your fixture decorator can be anything. It's up to you, so you can use direct values there if you want to, or in this case, I use simple strings, which then I'll probably use later with an if statement or something. But you get access to the parameter being passed in by this request.param attribute on the request's fixture, and that's how you access them. Another sort of building on top of that is if you have multiple fixtures with parameters, you can combine them, which is basically what the last function does. So in this case, because both fixtures are parameterised, Pyder test will basically call the last function six times because it requests both of these, and you will get each combination tested automatically. So in this case, the example suggests that I want to test the connection of both IPVC four and six, but you automatically get all combinations of your fixtures. Byl, sort of slightly building on top of that is, you can optionally mark your parameters again in your parameterised list. So in this example, I don't assume that every developer has their Oracle DB API installed. So I just try and put Oracle, if not. Yn y trofodaeth o'r hyn, neu mae'n ei gyd yn gwyfwng. Mae'n trofodaeth... Yn y trofodaeth... Mae'n trofodaeth o'r trofodaeth. Na, mae'n trofodaeth at y trofodaeth sydd ar gyfer bod ysgol, mae'n trofodaeth ar gyfer bod ysgol, neu mae'n trofodaeth ar gyfer bod ysgol. Ond yn f sings parodydd ei cyfnog, mae wedyn boden nhw dych chi'n meddwl y Facebook, a dyna bod i'r hoffi yn bod teacherswyr mewn ffwrdd. A yn unrhyw wedi cyflog a phobl i'r hyn ymddangod o dowod, W ysgol, mae dweud o'r mwyftu sy'n gwneud y cofnodol ar y bai oherwydd mae eich byddoedd yn gweld iawn. Felly, mae'r amser dysgu i ddyliadau hynny yn fy mwyftu, mae'r tuïn hubau bywydau yn desg gynuno cwisio, ac mae'r tuïn hubau bywydai eich busg yn ôl染ol, ac mae'n ddiogel, dwi'n ddysgu'r cyntaf, ac mae'n fwyfynol o'ch eu emer yn wneud am y plannwyr. Fe ydych chi'n fwyfynol, oe'i cyfrifio'r ffunctur, o'r rai gweithio ar gyfer ymdegol, oherwydd i'r un gweithio ar gyfer ymdegol sy'n gweithio a y dyfodol yn dweud. Yn ymdegol yma, mae'n ysgrifennu ar y gyfer y Pytus Django. Yn ymdegol, mae'n gweithio ar ddigwydau yng nghymru, mae'n dweud i'r ddechrau yng nghymru. Mae'n dweud i ddweud i ddweud i'r ddweud i'r ddweud i ddweud i ddweud i'r ddweud i'r ddweud, testfunction, so rwy'n cais yma, ym nesaf, yw'n dwy'n dwy'n dwy ffictiwys yw'r defnyddio mewn prifio ymlaen o'r dweud, ac dyna, mae'n sylwgr ymlaen o'r piysgau arfer o'r ffeilwm, yn ei dweud ar y cas, maen nhw yw'n dod yw'r teimlo'r the test function is asking and sort of have a look at the other fixtures around which sometimes could be a useful thing. Then sort of a very another sort of step aside I guess. You've probably if you've been using pi the test seen this contest of pi files but it so this is sort of typical directory light you'll you'll get and at the simple level contest of pi so you can declare your fixtures in there and then you'll see them in their entire directory basically. But contest of pi is basically from pi the test point of view it's just another plugin just like any other pi the test plugin you can install but it's a it's a per project kind of plugin and essentially when you start building a big test sheet you're going to be building a per project plugin kind of thing. The plugins work with this with this hook system so basically in your plugin you refine function with your hook. Pi the test will at certain times call these hooks then if you define one. These are just a few common ones there's a much longer list in the documentation. And I'll be showing like basically the add option one here which is sort of adding a new command line option. The parser object you get in that hook is basically just an odd pass command line parser so you can just use that documentation to add your options here. I'm here adding an option saying so basically the idea here is that if my for my script invoke spider test on my CI server I'll be just passing in that minus minus CI option so I know if my test is running on the CI server. And just very quickly like you can get to it to command line options both from inside fixtures as well as test functions again via this request object which has a config which is basically a pi test config representation so you can get access to both command line options or configuration file options in there. And basically the both request.config and pi test config are basically the same instance they're different ways of getting to them. And those two combining all of that together sort of I can this is sort of extending on an example I used earlier. So again so here I have this external service in this case a ready service that before I checked out is it on my developers laptop is it on my is it in the office or something but and I was just skipping those but in this case by using request of config and checking that option I can make sure that when I'm running on my CI server it really is going to execute and if not I actually get a hard failure so I can see so if the server is down I don't just suddenly stop testing part of my test suite sort of thing. So yeah that's another thing that we use quite a lot and it's pretty handy. Yeah that's basically what I had so far. Yeah thanks for listening I hope it was useful and is there also a way to get to the value of that feature then? Okay so the question is I showed how to get the names that the other fiction names that are being requested by the test function is there also a way of getting the value of them. The answer is sort of twofold definitely yes obviously by simply requesting it yourself but that's not dynamic. There is an escape hatch to do that dynamic although it's discouraged because so basically on the request fixture itself there's a getfunkarg value call which you can then use to call another value but so that's how you could get to it but generally that's discouraged because if you use that on one that's already requested it's probably okay but if you use that on one that hasn't been requested yet pie the test sort of loses its view of all the combinations of things and it won't be able to do its caching and scoping properly as well etc so you have to be a little bit careful but using that escape hatch I would call it. I wasn't familiar with the parameterisation that you could do with textures does that play well with the other parameterisation that you can apply two tests directly? Yes so the question is does the parameterisation on fixtures that you can do on fixtures play well with the parameterisation you can do on tests directly so on tests they're actually in case you don't know it's basically not the marker so you can decorate the test with at pytest.mark.parameterised and then give it a list of its parameters. Yes those two basically work together when you do so when you're requesting so when you use the decorator at parameterised you have to use the request and request.param again to get hold of the value that's being parameterised so when you're requesting request which is already going to be parameterised and all the parameterised fixtures just going to get all the combinations again so yeah so the question is when py to test and coverage are used together if you import stuff at the conftest.py in the conftest.py file it tends to be skipped by coverage and someone is nodding yes. The problem is the plug-in is it for a problem with the coverage plug-in what I just believe is I use the coverage good to run pytest and then there is no problem at the import level because the problem is that if you do something in fixture then that's not in coverage bringing this a plug-in. So the plug-in itself kind of can't catch that all as well. Okay so the new the new py coverage plug-in should be fixed so it should just work then basically. All right well if we're done then thank you again Flores.