Kotlin Power Assert

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello it's Duncan my regular viewer will know that I'm a testm fanatic I love to find new ways to make test more expressive and economic so I was excited when I saw there was a lightning talk at cotlin comp on power assert power assert is a compiler plug-in that enhances the regular coton assert function it promises to help us understand why test failed without needing complex assertion libraries as a developer with a bit of a complex assertion Library habit this is intriguing so please join me as I convert some tests from PL or J unit in the strict assertion library to see if power assert is testing methodone uh I'm teot well here we are back in kild dros after quite a while and after all the trouble I've had with gradal recently I should say that upgrading cotlin from version 1.9.2 to version two releaseed cotlin comp hooray was entirely painless so it's not all bad but we're not here to talk about Gradle we're here to talk about testing and in particular to look at Power assert in order to do so I'm going to look at List stock tests here it is and you can see if we ignore some Goins at the top that we create a price stock list we run up the app with that stock list and then we check two things we check that if we ask the app directly to load the stock list then we get what we expected back and also if we make a get request to the rout that we get a rendering of that stock list with this app expected rendering for there's that test there's another one that fakes out items here in order to show that we report errors not really interested in that and that's it okay so let's fold that one away and go and have a look at what we have here and in particular we're interested not in the way that we run tests but in the ways that we make assertions and the ways that failures in those assertions are reported so the first assertion we have is this assert equals here let's have a look where that comes from and the answer is it's assertions do Java inside junit now in fact I don't think I really should be using that let's just see why if I go back here you see that I'm checking that the apps load stock list is equal to expected stock list but in fact because this is junit I could put in anything in here and that would still compile now that's a problem with Java that cotlin can solve so if we were to go up here and instead of importing where is it J assertions assert equals if we took that out go and fix the issue and say instead we want the version from cotlin doest here you notice that's parameterized with a T So if we do this then you'll see that now we couldn't make that test we can only specify two types that are compatible with each other so that allows us to restore this and inside you'll see that this talks to an inserter and that eventually will just talk to junit so we're running the same code but we're a bit more typ safe and we are actually running tests today so let's go up here and we'll just say run all these tests good okay then so everything passes let's have a look at what happens when it doesn't so I think what we'll do is we'll just map this to change the thing inside the success and we'll say it dot and we will drop the first item from it and let's run that oh I see the problem we need to say it. copy with the items is it do items drop one okay let's run it and it fails and let's have a look at what we get so we get expected success of price stock list with some items in it and we get a click to see the difference which these days actually highlights somewhere in here yes like that where there are diffs but it's a bit unfriendly because it's all on one line but we can see that we're missing an item okay I'm just going to have a look at this assert equals again here it is and you can see that it's one a family of lots and lots of different assertions we've got assert equals T's and doubles because doubles have tolerances and assert not equals and goodness me well assert false assert true assert same not same ass certies and ass certies of type a whole bunch of different operations fundamentally they all kind of map back to assert true pull that in that thing equals that thing and if I run that then it fails as we expect but the problem now is that all the test Runner knows is that this was false it doesn't know you expected this to be equal to this because you can't look at this equal sign and decide that's what you're doing so that's the reason for all of these junit methods things like assert equals that it allows a decent error message because we know that we expected them to be true but for example if are not equals that would pass now oh well it doesn't but only because later on here we we've changed our expected price stock list so maybe let's just go and fix that up we'll have duplicate that we'll have we'll call this one not expected price stock list which is that one the expected price stock list is that one and then we can say let's just go and fix that up so we've got both lying around this is going to be expected price stock list and so if we now put not expected in here that passes as we expect effect but if we used expected price stock list that I seem to have renamed badly in here then the framework knows that I expected them not to be equal so it can give a different error message there we are expected not equals but worth something okay let's just return this to what we expect which is expect equals expected price stock list to be that and I think a better phrase would be unexpected and run good by the way if you want to know where that test Runner comes from it's it's courtesy of my friend Demitri kandov and I will post details in the show notes below so when we're making assertions we have to choose which assert we want to use in order to get decent Diagnostics out of it but what if that wasn't true what if we could just say assert which is actually a cin built-in thing there you are that that equals that well we know that that will pass when it's true and it will fail when it's not true and that we will get very little information out of that but what if we could get more information out of that both Python and groovy have a way of extending the assert to look inside here and make sense of it could we do that in cotlin well not with the language as it is but if we don't like the language as it is it is possible to change it with a compiler plugin and that's what we have now in paraset so paraset was written by Brian Norman here it is on GitHub and I've known about it for a while but the thing that's put me off is the compiler plug-in and the fact that down here we have to manage cotlin versions and plug-in versions and so on and frankly I wasn't sure that Brian could keep up with changes to the cotlin compiler however it turns out that Brian Norman now or maybe always worked for jet brains so the power set plugin has now been brought into the standard set of plugins available with cotlin it's experimental but with this information I think it's a lot easier to take a punt on so let's see how we install it the answer is we add power assert to our build let's copy that and before we go on we'll just have a look it says configure the plugin it will by default change coton insert calls and work with test resets well that will do us for now so back to our project and in our build. gradal go back up to the top and add the paraset plugin you saw down there that things happened so I think it's probably installed let's run the test again it failed as we expected let's see what we have so now instead of just assertion failed we have assertion failed and a diagnostic of what was going on when it did so you can see it's broken this statement down and it's told us what our unexpected price stock list was there it is it's told us that the test turned out to be false it's told us that the app was well this app here with some inmemory items and so on and so on and then the call to load stock list resulted in success of a price stock list that we know won't be the same as this one now then compared to the assert equals this is both better and worse it's better because we showed the context around us we showed what the value of app is in here we shown some other parameters that I don't fully understand which showed the actual this one and the expect did this one but we're not showing them in a way that we can compare easily if you remember when we changed this to be equals then we got less information about the context we never found out what app was but we could at least click on here and see what the diff was in return for losing that diff we can pretty much always just use assert so we don't have to decide that we're using assert equal or not equal or whatever if we want to use not equal in here we can say not equal equal to and then we could say expected is not equal to that get R of that one and if I run this you'll see that we get a very similar Trace as before the not equals is false and we got all the information about the two sides of the comparison we could also use something like expected stock list. value. items. size is greater than load stock list value or null items size and then we would get information about the sizes put in there you can see each part of this expression we're being told his value I'm not entirely sure why we're not seeing the value of these intermediates here I wonder if I change this make this result of a success of price stock list I could make that happen by moving this price stock list into here so I could say that this is price stock list and then I wrap that in a success make this price stock list item now I shouldn't need to do value oh but I haven't actually changed this side here appload stock list H yeah don't really understand that I'll try another trick which is to say that this is a variable pull it out of here so we can see it we're not really interested in the app inside this assertion so I think we could say this is value or null and we know that isn't the case and now this would be value items size that can go does that give us better yes it does interesting so now we're seeing the value or null which isn't the value it is the value from app and now here it's drilling down through the price stock list to the items to the size and when I say drilling down I think I mean drilling up but you get the gist just out of Interest I wonder what happens if I replace this with function call and run that and there you go you see we don't have to use operators we can use any expression that evaluates tolean inside here so I think we can predict that the compiler plugin is having to remember this entire expression when the code is compiled and then if this works out to be false evaluate the individual parts of it and make that into a nice message like this okay I'm going turn this to what we really want which is the expected stocklist value equals the value from app and then I can inline that removing that oh but that needs to be an equals good so an interesting side effect of this is that we get out information according to what's inside these brackets so again if I was to pull this out as a variable and call it loaded stock list and return this to unexpected then if I run this I just see this as its value whereas if I inline this and run then I see the value of the app and the result of running load stock list on it so we can tune our output by what we include inside the function call and I suppose if you want to express the fact that we're only loading the stock list in order to check it we could pull this out as a variable and then we could do the dot Elric of moving into there like that and then move this up into here and then remove that and then make that an IT and intelligent is saying oh it could remove the electrial force well thank you but that was kind of the point but I don't want to give you that so let's go back to that version which I think is clear enough okay then what about the second test down here this is using strict which I covered in the previous episode and with strict we start with the subject so we say that expect that subject and then we can have matches on that subject this status is from an hdpk extension to strict and the same with body string so it's a nice fluent expression and we can always inline this into here and things are still the same okay but the question is why are we doing that why aren't we just saying I'm going to do it in Old terms so we're going to say assert equals well now actually is going to be this request route this thing here and I expected well we could just F the response because responses are just objects in hpk so we should just be to say response with the status of okay and with a body of the expected rendering for the expected stock list so like that and before I run that the way that we express that thing in strict would be to say that we'll take that thing we'll expect that app Roots dot is equal to a response that looks like that so that would be the strict equivalent of assert equals well let's run them and find out why we did this instead of this and here we are failure and got a nice diff so let's use it and the left thing is what we expected and the right thing is what we got and you can see that on the right we have some extra HTP headers in this case the content type that was added by hbf and some Trace IDs now the content type we could have set into here easily enough but these Trace IDs are randomly generated by our app and randomly generated is kind of the point I suppose we could F around with mock U ID generators or that sort of thing but that's complication we really don't need so we either check just the bits of request that we want or I suppose that we could say here that we would take our response and remove all the headers and if I take that one away because we don't really need it I think that might make it pass and does so we have two ways of making assertions on only part of structured data one is to select the bits we are interested in and one is to unselect the bits that we aren't interested in and strict is very good for selecting the bits we're interested in because in here we had the global object here and then we're picking bits out of it and in fact we need not have been using HTP Fork's versions We Could in here have said get status like that which would have been the equivalent okay let's see what happens when these fail so let's take the unexpected price stock list and expect the rendering of that and run okay so this is the test that's failed let's have a look see what we've got so we've got assertion failed there click to see the difference and oh that's really rather nice we can see directly the the response that was different we got to the top you see that we had the whole HTTP response and and neither have headers because we took them out of the respon on the app so that's really nice let's see how strict does we will swap these over so we'll make this unexpected and this one no the other way around run and again we've got a failure as we expect and okay scrolling to the top strict when it fails describes the expect that so it says expect that this thing which is our entire HP response including the trace IDs because they were there we didn't take them out lots of cubbins and this is that unfolded and then cross for not is equal to this thing so this is the version without the headers and then found what it seems to be repeating itself a bit but we'll let it off and then it says it again I'm not quite sure why expect that to that and it shows you what passed and failed so it shows you that the value of the property status was equal to 200 okay and then down here that thing which is the body was not equal to that thing so it's able to make a description of this entire block here and tell us which bits passed and which bits failed that's very nice and it's the reason that we like strict but no compared to this assert equals if we wanted to get into why the body strings were different we'd be copying and pasting into buffers and comparing them and so on let's let power assert have a go at this first one so we take that put it in here we just need to change this to equals equals and we want to make it fail so we'll say unexpected price stock list I'm going to make that back again before I forget and run that failure as expected let's have a look we'll go all the way to the top and we'll make this as big as we can okay I think I've made things harder for it by splitting it into more than one line so let's stop doing that go back that's the one that wants to be on one line let's do that and run and go back up to the top ah there we are well I imagine that if you trace some of these down you would see them all the way down here somewhere yes there you are you can see I think the values of these things coming out against the pipe character that lines up at the top so again we're getting the values of all these Expressions but unfortunately they're multi-line strings and as with strict actually it's not coping all that well so let's cast this a bit more like the strict version instead of removing the headers and testing one big thing we're going to test the individual bits so let's pull them apart let's say this is a variable for for oured rendering we just do this one we'll call it actual rendering and actually I think that isn't the actual rendering that's the response now then let's make two assertions we'll assert that okay equals the response. status and we'll assert that the expected rendering is the response do body string and we're still using the unexpected one so one of these we expect to fail let's have a look okay back to the top and see what it says H and here you can see we're just looking at Big multi-line strings where I think we know that assert equals would have been better but again should it come in handy because the responses in here not just the body string we are going to see a rendering of the whole response and then a rendering of the body string now what we might want to do instead is say well look this is just a Boolean let's take this and we could say that equals that and that equals that so I can get rid of that and run now you can see right down here we we're showing the results of this okay equals response status here is true here and no doubt there'll be a rendering of all this up the top goodness me yes but you see we're seeing all the bits of it however I think there is an issue which is if we said we wanted im a teot and tried running that that fails as we expect with IM aot is false compared to the status but know that we haven't got any pipes under this bit so we're not seeing what the expected rendering is or the response here well we see the response here because it's the same response but we can't see what the value of response. body string is and that's because short circuit in this and means that this second bit here was never evaluated so compared to the strict version that would have shown us this even if this has failed we're not seeing the second part of this expression now parer has a suggestion for that which is soft assertions let's go and have a look so the idea here is inside this assert softly it will collect errors and only report them at the end so let's copy that add it to this file here now unfortunately we now need to configure power research to know about this because it's in our code base and not shared anywhere else at the moment so the package here is com gilded rows and it say assert softly let's go back now we need to configure the plug-in let's take this which is cotland DL never mind back to our build. gradal down the bottom paste that I think we might get away with just saying that is power assert and then this is a groovy array and now this is saying I want you to enhance the cotlin assert which is one we're already doing the cotlin test assert which we haven't been using but also this would be our version which is com. gilded Rose okay back here armed with this let's use assert softly so now in here we can say get that and then assert softly some things assert and now this version Maps to this one which is implemented as this one so back here so now we can say assert that and assert not softly expected rendering is body string nothing thing so let's take that and run see what we have scroll Way to the Top assertion failed IM aot is response. status so what are we seeing we're seeing H well this response is now our entire response so we're seeing all of that a little bit tediously although that might come in handy but no we're not actually seeing anything about this one here at all because it didn't fail so again I think probably we don't really want to see this entire response maybe we do maybe we don't but we might say response. status dolet assert imot equals it and then when we run this we would see only the bits we were interested in yes and we are in fact failing the second bit because we're saying the unexpected price stock list so now we've seen the second failure as well and we've seen the amation of those two failures we're not just stopping when this one fails if it didn't fail though and we made this expected price stock list then the first one would fail the second one wouldn't fail but we wouldn't hear anything about the second one at all very very simple compared to the strict version here where it will actually tell us what the body string is even if it's only the status that fails so horses for courses I'm just going to return this to okay so that everything is all right and then finally it's a bit irritating that we have to configure power assert to use assert softly but I think there's an alternative so I'm going to take this out of here because Jun actually has a way of collecting multiple failures so instead of this assert softly we could say assert all and you can see there's a set of overrides here fundamentally the one we want is this one here that takes a vog of executables which are unit to unit so let's import that and now we can give a set of lambdas that are the assertions and now if we undo this and move this one into here and move this one well copy I suppose into here now we were passing and we'll continue to pass but if we change this one to be uh I'm teot and run let's have a look at the output now okay back up to the top we're still getting the output from Power assert so assert IM aot is response status we're still drilling down now into the response that's this one here so we're seeing the entire response C the power assert and junit is marshing these things into a multiple failures error where there's one failure so this is the report of the multiple failures error if we failed twice then we could say this would be unexpected price stock list so I could now take this and put that into there if I run that then we should get a multiple failures with two failures in it here we go multiple failures error multiple failures two failures so it's reporting the first one here and the second one I'm sure somewhere else for some reason junit seems to show the failures twice so we're seeing the two individual failures and then the multiple failures which is then rendered as the two individual failures go figure so this assert all can allow us to collect together a number of failures with power assert reporting but doesn't do the nice strict thing of showing you things that passed as well as the things that failed also what we don't have is this idea rest strict of the subject but we can solve that problem I'm just going to take this away I think for now so we can come down here and see let's get rid of that and all its little Wizards and now what I'd like to be able to say I'd like a function that for some T was ass cert all taking subject which is a t and a varag set of assertions each of which took t as the receiver and returned unit because they'll throw if something goes bad and we'll call these checks and how could we Implement that well we can say assert all there's a version of this that takes a string that describes it so we're going to say four subject and now we need to map these checks into lambdas so that is JS map and then we can take the Lambda and apply it to the subject then I think if we map that to org. junit do jupiter. API doer all some sort of issue let's find out what the type of that is ah it's a list of unit what we actually need in here is a Lambda inside the Lambda that will now not be list of unit but list of function that takes nothing and returns unit so now we can inline that now we we can say I'm asserting all on the response and these lambas will have the response as their subject so we can get rid of that and we can get rid of that we'll return this to expected priced stock list so that we can see how that does and let's run that back up to the top and now if we find the multiple failures error here it is so it's saying for HTTP okay it's now listing the entire response which is the subject well I suppose we asked for it so we got it and then it's saying there's one failure it's assertion failure which is I'm a teapot is not equal to status and I think because it's the receiver of status we're seeing not only the 200 okay but we're seeing the entire receiver here so that we can see the subject all over again for our delectation and Delight I suspect that will be tided up quite a bit if I just put that in there and then we just going to return this to okay so that everyone is happy hooray so which assertions Library should you use in this project we have looking down here it turns out assert that from Ham Crest we have junits assertions we have cotl test assertions we have strict assertions and we now have power assert and other assertion libraries are available this episode is already too long so I'm going to kick the can of that discussion down the road to another episode if you'd like to see it when it comes out then please subscribe to the channel if you click the like button you'll find it easier to come back to this video when you need it and if you want to help fund these videos then you can buy a copy of the book that wrote with that price called Java to and refactoring guide book details which are in the show notes below thanks for watching
Info
Channel: Refactoring to Kotlin
Views: 820
Rating: undefined out of 5
Keywords:
Id: ujxNvC_Q_cA
Channel Id: undefined
Length: 30min 16sec (1816 seconds)
Published: Fri Jun 07 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.