Golden master testing with approvaltests.net & FsCheck

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody and welcome to a new quick video this time we're gonna talk about call the master testing and we're gonna use two library's approval tests and FS check to make our job easier in order to get started I'm going to take a look at our Akata it's a little you don't know cos use our little programming exercises you can use to try out new stuff to get better at things like unit testing refactoring today we are going to use the gilded Rose refactoring kata to introduce these two new tools let's open up the repository so Emily beige has a lot of chaos in our github and one of those is called kill the grouse let's scroll a bit down and find the description I think this is the one yeah so a quick quick problem description we have been employed by the gilded rose and the gilded Rose is a small Inn and they sell stuff and they need some kind of inventory tracking system that keeps track of the quality of their items they have in stock all items have certain properties like a quality that goes down a sell in value that goes down the quality and selling decrease every day so that's the problem statement there's some really nasty business logic in edge cases because this is real life and now a new feature comes in so we're asked to implement conjured items and these have special rule set saying that the degrading quality twice as fast as normal so that all makes sense you're an eager programmer and you want to get started well in comes the code code is pretty nasty so open up some codes this is the gilded Rose code and it's pretty pretty hard to follow there's a lot of branching there's a lot of nested conditionals so it's one two three four five levels deep so it's pretty interesting to figure out where this new feature of conjured items would have to land in this method so we are asked to implement this new feature but we are going to refactor the code a bit first to make it easier to add this feature in it's a bit like the saying from Kent Beck first make a change easy warning this may be hard and then make the easy change we have another challenge or not a problem this is the entire project code so we have gilded Rose this is the system the business system we want to test and we have another class called items just a property bag containing the name and the quality and selling value and that's it and what I'm saying that's it I mean there are no tests so when we start to refactor this piece of code we have no safety nets to catch any mistakes we make code without tests it's called legacy code in a very good book it's this one working effectively with legacy code by Michael feathers and he defines legacy code as code refrain change or coke without unit tests so today we are going to add tests around this thing in order to safely refactor it later we're not gonna do the actual refactoring today we're just gonna show a way of easily adding our regression tests around a piece of legacy code and the strategy we're going to use is called a characterization test it's also straight from the book or maybe read like the definition the characterization test is a test that characterizes the actual behavior of a piece of code so we're not designing any new code now we're just trying to make sure that we catch the bit current behavior of a piece of code inside a test and that's called the characterization test and he also has a little process in here like how do writes how to write characterization tests it's a five-step process is really simple and it's called it's goes like this first you use a piece of code so we will have to use this gilded Rose topped update quality method then we write an assertion but we don't know the expected behavior yet because it's really hard to follow code so we just do some kind of idiotic assertion like assert that the empty string is the same as the actual output so that will fail by definition almost or I hope that will fail and then you have the output in the error message you can copy paste that into the accepted step expected step sorry and then you have your unit test for the current behavior so that's the broad strategy we're gonna apply here today it's called characterization test but we're gonna use a very specific flavor of characterization tests called golden master let's drop back to the slides real quick so our goals for today are to get this code under tests with minimum efforts and with a maximum safety net for any possible regressions we might introduce during refactoring cool we are going to use the technique called call a master testing and the process of a goal of master goes bit as follows you generate a whole lot of random input data so in our case that would be the items for the in for the minute the quality management system then we run the gilded rose behavior with this deterministic set of large set of input data it has to be deterministic this is a really important part because you have to run and rerun this test and you would like to get the same output every time so that's why it has to be deterministic but it can be random in the sense that you don't have to think about the cases all that much you can just generate a whole lot of items with all kinds of different names all kind of different qualities stuff like that and you hope you cover enough when you run the system with this huge set of data you can capture the output and in realistic legacy code scenarios most of the time it's log files or events going out or messages on a messaging infrastructure but you can capture for any kind of system you can capture most likely some kind of output and if you can maybe that outputs the same every run like you strip away timestamps strip away irrelevant data like that and just have like textual representation of the expected output you run it once you save that output on the first time you of course take a look at it so so you're sure that it represents a valid case and then you save that output to a file or somewhere you save that expected output and that's called the goal of masters so that is the truth this is the output we expect every time we run that test and then when you start refactoring and you start rerunning this test you can run the test and compare the current output against that first initial golden master output and if there's any differences you know you broke something and you can start to diff the two files or the two outputs and see what kind of thing you broke actually so that's the broad idea we're going to be using two libraries to make our job easier today one is called approval tests and I think it's almost the de facto standard for golem master style testing approval tests is a library that allows you to do v based testing so I'm just gonna show you in a minute or two it's a bit of abstract to explain but basically you just write a test you say approve me this output first time you won't have any output so it'll just pop up a screen say is this what you expect if you like the output you see you can approve it and every subsequent test run of those tests will compare the current output with that initially approved output so you will notice any differences the second library we're gonna use is one I encountered when I learnt F sharp it's called FS check and it's library for property based testing property based testing is a complex topic in and of itself but we won't go really into the property based aspects of Evers check we're gonna use a little part of it and it's called generators so generator is basically our way to generate data of any type P early at random on the fly without having to write any code ourselves so we can generate random numbers random strings but even more impressively actually you can generate the data for custom types so for example in the gilded Rose cotta we have that item class we can leverage the FS check generator library to generate random items for us and is exactly what we're going to do today alright let's get started so I pulled in gilded Rose I threw away all the dependencies just to make a point so we have no nugget packages nothing we just have code code dead compiles there we go step one is I'm going to pull in those two negative packages let's first install approval tests there we go let's install F is check there we go and next let's install some kind of unit test framework my favorites frame of the Shuar is a X unit so that she's good for that okay we've installed everything I'm gonna write a quick hello test to make sure everything is up and running so let's write a new class I'm gonna call it golden master already there we go let's write any tests okay my shortcuts are not working that's not a problem let's write it so let's write a new test public Ford's no useful name just yet and let's make sure our tests are running and failing the way we expect them to there we go so this should fail we have a failure yeah expected true actual false that it's correct let's make pass just to see be a green test as well so yeah X unit we have X unit up and running next step let's check if we have approval tests up and running so let's do a very basic system under tests so we have for example inputs is hello and let's write some business logic for reverser and that's what we are going to test is a function that takes a string a function that takes a string and returns the reverse of the string oh my god is this something yeah I'm making things too difficult say we're going to do input is a number and we're gonna calculate something it's the number plus 5 I'm doing something completely random right now but say this is my test input and this is some kind of behavior I'm testing right now it's hard-coded inside the test but just for illustration and then we're gonna use approval tests to verify the behavior so let's go to the approval test namespace and do approvals dot verify can it take a string yeah it can take basically anything even objects I'm curious to see how that works actually but okay for the demo we're gonna use a proof and what are we going to verify we're gonna verify the output and we call this variable result in here so this is our first approval test actually we have some input we call some code and then we verify the results we verify the result that's really weird because normal unit is have this compare this to that and make sure they're the same kind of thing here we just say verify result let's try to run that and it fails that's expected and it's actually a cool error message because it's very self-explanatory we forgot to do something or I'm sorry I forgot to do something and the test is Joe the failure message is just saying hello welcome it's a really friendly API code but it's saying okay please add this attribute to your class method or assembly why it's even explaining why we should do this and down to approval tests use your diff to of choice to present any kind of failures so if the approval test starts failing it will really open up a diff tool and say look at what's changed so that's really cool and we're gonna show it later but it's saying we have to take this attribute and put it on our test or a class or whatever so I'm gonna do that yeah we're just gonna take that over literally I'm gonna rerun this test now yeah and now it's opening the diff reporter so it's opening the diff tool visual studio and I was about and it's saying we have a dot approved file so this is the golden master file all right and on the left is the current run and saying whoops it's failing because we don't have an approved file miss so what you normally do is you take the input from the first run and you paste it into the approved file so now you're saying like this test and how do you know it's this test because it's the class name dolt method name of the test dot approved and this is what approval test will look for when running subsequent West's tests so now we have this file run delta p-- rooftop txt somewhere in our solution and let's pull it in to do code solution explorer as well so we can have easy reference to it it's a text file so you should be able to find it this way there we go so this is the caller master file for this specific test and we expect this output of this thing to be base six I don't know if this space is going to be what expectancy so now we have a space where there should be none there we go so I changed the dot approved file and now it should be green everything goes well there we go so now it's green and every time we run the approval test or this test we will do the diff and if it's okay it's green if it's not okay we will get a diff it pop-up interface showing the difference so say we are refactoring this really hard piece of code right here and instead of adding five we subtract five and let's rerun it so we now introduce the book this is what Google gets so this is what we got this draw round run minus four but we used to have six something changed this is the power of approval bists we just wrote these three lines and we can have very broad regression tests around any kind of code where we can capture some output which is great so let's fix that test again make it green this was the principle of approval tests and we're gonna use this to wrap call the master test around we build the droves next up let's try running guild droves so let's go to the killer dress codes and see how we can run this behavior gilded rose is a class it has a constructor that takes a list of items cool and it assigns the that lists directly to some kind of prime property over here and then there is this methods in this method contains behavior were interested in so we want to start refactoring this so we need tests around this kind of behavior some interesting aspects about this method there are two interesting aspects of an orange method one it does not take any arguments so it will work on the internal state probably yeah we work on items panelists and to its avoid methods void methods are side effects so it will do something to the internal state probably and as you can see here yes it is updating quality of items in that array so it is actually producing side effects okay let's try to execute this method so what do we need to execute it we need gilded rose so I'm just gonna call it rose is new gilded rose and it takes a list of items that just provide an empty list to get started now we have the rose and Rose has a method update quality that's it let's calm design first seconds so now we have a Gillard Rose we can provide items and we can run behavior and then we could actually verify stuff how can we verify stuff well let's say we extract this list there we go and then we can for example approvals don't verify the list of items it's not gonna be very interesting right now because it's an empty list so let's see it's even an artist ringing the list so that's not actually what we want but we'll get there we'll fix that in a moment so this is the approach we're going to take we're gonna generate a huge set of items we're gonna feed it through get rows we're gonna trigger the behavior and we're going to check where the items have been updated accordingly cool I'm gonna do this for one item first and we're gonna handwrite the item just to get a feel of what we're doing here so let's make a list of items there we go let's add an item to his list so we have an item let's give it a name it has a name my magical item will give it a random quality because we don't know anything about the problem domain just yet so I'm just gonna give it something some value same story don't really even know what it means so we have an item we run the gilded rose behavior over it and then we're gonna verify this this is still a list and we don't like to see the to string representation of the list type so let's capture the relevant in item information let's call it output this items dot select we're gonna map over the items and to string them basically so do string the item now we have a list of strings yeah a list of strings maybe that's even good enough to for approval tests let's try that so approve the output and that's a list of the item information let's quickly go to the to string method we already have it's printing the name comma selling value comma quality it's cool run this approval test nope this was not enough so we still have a an innumerable instead of a string and approval this does not like it so let's go back to our test and we have a list of strings here let's just join that together with string join new line separator and as values we take what we had here so item details and now we have a single string where every line in that string is I do information this should probably be better there we go so my magical item has a sellin of 19 and a quality of 12 so it seems like it's ticking down both when we call a bit quality okay let's prove this by copy pasting what we have this run and if we rerun the test now it's green and if we render in the test again it's green again and this is basic gold master principle I'm gonna run unit test coverage really quick to show how much of the code are currently covering with this one single my magical item case so with this one single case we are covering 36 percent of the behavior so let's highlight it and go to gilded rose every line in green is the line we are executing under running our unit test so it seems like we're falling into this branch to decrease the quality but not over here we are also decreasing selling but there's a lot of edge cases we are currently not executing so this single test would not really provide much of a safety net for all the behavior in there so let's grow our items bucket or list items let's add more items so we cover more and there's two strategies for this one is to start inspecting the code inspecting the coverage and seeing okay what kind of items do I need to have the tests execute this branch and it's a really interesting exercise as well and it will help you gain business knowledge by reverse engineering the code but there's an easier or not easier there's a faster way and you don't have to think that much to get the test around it and that's what I'm going to show you today and we are going to generate a whole lot of add items and we're going to generate them randomly using that FS check library so we don't even have to think that much and get a list of 10,000 Ivan's no problem so FS check what is FS check probably base testing library already said it but we're just gonna use the generating of random data part I'll give you a quick rundown on FS check I'm going to use the c-sharp interactive repple to show you the the beginning API for generating data is our table generates and you provide the type parameter like int there we go so this is this statement is a generator for kids if you hover over it the type is gen of end so this thing knows how to generate random ends sorry I'm going to play around a bit bit with is that in the ripple so I can show you what this thing actually means and for that I'm going to load in the FS check dll into the ripple you need to drop down to I need to find the DLL for that so let's go to my binaries over here is that a good way to do it yeah sure if it's checked out DLL that's the one you want so copy/paste my path and require that in here FS checked off yellow so first we load their DLL into the ripple and then we X you open the namespace so I'm just gonna run this in the rebel now we know about ARP and stuff in the rebel cool and now I can sense random c-sharp to the repple there we go and now we have this generator to play around with so this is the actual an actual generator there we go FS check provides some utility functions to troubleshoot generating and that's what we're gonna use to play around with it I'm sorry and just hit my mic real hard so there is a method called sample or a function and you give it a size more on that later but just let's give it something and number of samples that means like how many of this do I want so generator is a gen of int and I want let's say five random integers if I run that it gives me a list of 1 2 3 4 5 random integers so this is basic FS check generators and this is just an int but you can use for Strings for pools for characters for any kind of data and what's really interesting you can use it for custom types so classes you write yourself let's give that a try I'm going to write a class public class what are we gonna what are we gonna design today coffee that's right we're gonna design some coffee what just coffee have property wise let's give coffee a name the bean yeah and let's give it a an integer probably uh let's give it a strength or an intensity level so higher intensity level means a stronger cup of coffee so this is a class coffee I'm going to send it to your Apple as well there we go so now I can play around with coffee in my rebel there we go let's make some coffee ourselves new coffee name is a rabbit car I know nothing about coffee so I'm sorry if I'm inventing new kinds of coffee so ok now we have coffee but instead of generating or calling constructors manually and generating a whole lot of coffee let's use the F sharp F is check sorry generators so to do that you do our dots give me the generator for my type so the coffee generator and that's let's go match in there we go now Jen generator yep and we can sample some coffee let's say we wanna have three coffee objects and it gives you three coffees one with a very lucrative name PR seven - when intensity three the stiff - three calls you ASCII code something something so you see FS check is generating strings here and it's generating like all the edge cases you could think of ASCII escape characters no letter characters so it's really useful if you want to do like testing against rest endpoint they want to make sure it's really hard and then can handle all the edge cases but in the case of gilded rose or when you're generating coffee samples those kind of strings are pretty bad they're not self explanatory so we're going to show a way of composing different generators to make more meaningful coffee types and more meaningful item types but the principle is F is check you don't write any code and it can generate magical objects for any tape type you can imagine and we're gonna leverage this to generate a whole lot of items for our golden loss to test now so let's get rid of the coffee let's clear our rebel screen and let's get started so we want basically we want to have a whole lot of items that's our goal here so this list of items we want to generate this using a face check first to guess our let's generate a single item so let's make something called an item generator gin or eight or and it generates ideas there we go let's send this to the repple know the type or night I did not import the current project so let's import this namespace c-sharp that does not work because we don't know the currents yellow guy send it through here is there a sense to interactive on project level stop me if you see it I'm not seeing it yeah and here there we go initialize interactive with project so then it'll load all the things oh that's even great it loads so f is checking everything so now we have every reference we have needs it's cool so ripple knows about everything let's send item generator voltage ripple oh it still doesn't know about FS check so that's important it's check there we go now we can rerun that item generator there we go and we have an item generator and let's sample some values for it let's generate 10 items so these are 10 items but they're really boring items the name is and selling value is minus 1 qualities minus 2 so it's a really useless kind of item especially if you go to the business logic you see that these items all have like there's a an item name is not just a string apparently there's these all kinds of special cases and of course we would like to include these special cases in our test set as well and if we are just going to wait until a fish check generates a string containing the exact characters of age debris that won't be very effective I think so we're going to show a different way of generating items using this check by helping F is check a bit so let's even take a smaller step than trying to generate an item let's try to generate a valid item name so we have name generator and you could do the same again so generated a string but we've seen before here those item names or those strings generates are not really interesting so we're going to show another part of the FS check generate your API and it's called gem and is the class name space gem it has a whole lot of functions and one of those functions is called elements there you go and takes a parent or a numeral of values and the it will return a generator that generates one of those failures in the case of these item names that's perfect so for example let's take aged Brie another item name is backstage passes to some kind of concert sure there's another one so first hand of Ragnaros so these are the items in code three items that exist in the special cases and for good measure let's add a fourth one namely my magical item down here let's add that one in the item names as well so we have the long edge case path as well so that's some this to the repple now we have a name generator and if we ask this generator to generate some data give me three item names for example it will give you three random item names this is great so now we can generate item names on the fly in one line of code okay we can generate item names we can generate items but how can we generate items with those random item names well this is where F is checks functional nature comes to show it's a library for F sharp F sharp is a functional programming language and one of the main selling points of F functional programming is you can compose everything because it has no side effects you can compose all the things everything is a function and you can give input functions to functions and you can output new functions and we're going to use this now to combine multiple generators into an item general that suits our purposes so in order to do that we're gonna use link grace index because I hit the mic again sir we're gonna use link query syntax because I think that the easiest to understand without having to earn a PhD in functional programming so how do you combine generators first now first I'm gonna create another generator one for the quality in a cell in value and you see some value with an end quality isn't ins so I'm just gonna I don't know if it's a good idea or not but I'm gonna do a number generator so we're gonna use this generator for both and we are going to generate ins we've used this before I know so let's send it to the repple again and let's see number generator give us a sample give us some examples let's give me ten numbers is this okay it looks like interesting quality and seven values let's go to the code real quick what are we seeing about these qualities and sellings quality around 50 that's an interesting case selling around 11 so we have to make sure our generators hit these kind of numbers 50 11 okay cool currently the random numbers look like they might not hit 50 no maybe a quick peak if you increase the size you get bigger numbers yeah okay so we're gonna get there but okay we have a generator for names a generator for numbers and we would like a generator for items based on those two generators we have before how do you do this it's really easy with link syntax so links index is the from select kind of thing it looks like link a sequel sorry and it's c-sharp code so how does that work from name in named generator so this translates to when you run the name generator and extract one of the values out of it you can bind it to this thing called name and you can do something with it in a select statement for example create a new item objects and give that item the name that generated name we pulled out of the name generator over here so this link statement is basically building a generator for items using the name generator to generate a random name preventing it if you look at the type of item generator it's not an item it is a gem of item so this is where the whole functional monads magic comes but don't worry about that this is just syntax to combine generators let's call them so now we have a generator that builds on the name generator and generates items let's run that real quick so name generator item generator let's generate an item using the utility sample function you see it generates an item and it has really not an interesting quality sell them because we don't set those values but it has an interesting name it's one of those in the name generator now let's provide the items with interesting quality values so from quality in number generator so we just extract from number generator which is an INT generator random int and we provide this as the quality fields well what's happening there we go let's run this generator let's try it out again to make sure we're still on track there we go so it's generating a quality of -4 looks good let's do the same for selling so let's extract a selling value out of the number generator again and let's assign this to the item quickly run it in the ripple we have H bri74 40 minus 3 that looks pretty good actually is it I don't know which one is which interesting okay nevermind so this is a generator of items and will generate completely random based on this list names and completely random qualities and seven values based on this in generator and this generates one item but we don't need one item we need a bucket load of items so this is another utility function and FS check let's create a generator generate or and built upon that item generator we just created to create a list of items generator and the way to do that is in the gen class again or engineering space you have a list of function yep and you give it a list of given length interesting forget it we're giving this a another generator so the generator for items and if you look at the type of the items generator it's a gem of blah blah blah sharp list so it's a list for all intents purposes of item so this generator knows how to generate lists of items hey that's exactly what we need cool so instead of this hard-coded value over hard coded example let's generate some items out of this generator and you could do sample but I don't think sample is deterministic so let's give it a try here if I run sample and rerun the sample yeah it's different kind of item every time that's something you don't need and can't use for I call the master test you need deterministic random data and there's a another function in there from generators it's called eval so it evaluates a generator and it takes two parameters the size and a random generator or a random number generator sorry so let's give it a size more on that later and a random number generator I'm gonna use another fun factory function Lucy no makes them Jen yeah so this is a random generator and you can seed it so you can give it a value and every time you run this it will return in the same sequence of random stuff so let's send everything to the repple again and try it out there we go so items should be a list of item yeah it's a list of five items namely h bri so for as some other agent read some borage breeds more sulfurous so it looks like it's not really generating a whole lot of different items so it's interesting but okay let's start we have red squiggly lines in our tests and saying cannot convert a sharp list to list that's technically correct and a sharp list is not a list but you can do something on this list namely two listed pam and now it's a c-sharp list like we all know and love and Gil approach would accept it so now we are generating random items we are feeding them to gilded rose and those January values are deterministic so are the same every time it's exactly what we need and we have our approval test run it so let's just run it and look at the difference just to fail really bad there we go okay let's prove this copy/paste man thank you and if we rerun this test now it should be green should stay green unless we introduce a book so I'm gonna introduce a bug no I'm not I'm gonna show you later so now we have a call the master but is is golda master effective are we covering all the edge cases let's rerun our code coverage - there you go we are hitting 49% of the code Oh highlight it again real quick so we are not hitting every branch in the code that's too bad we could fall back to providing manual cases again to cover all those special branches or since we are brute-forcing today using an F is check why is this what are you in my face system string okay there we go since we are brute-forcing item generation there's not a different approach and it is to turn it up to 11 basically if you increase this size parameter F is check will in generally generate longer strings longer lists bigger numbers so it will increase the size of data that gets generated so I'm just randomly running this randomly increasing so as you can see this run is generating a lot more a lot more so add some kind of say 600 items so that's better but the thing that's interesting for me is if I look at the quality and selling values those keep being - one two - skete they remain really small so what we're gonna have to fix that first it's generating small values and if we look at where these headers are coming from selling and quality are coming from number generator and it's just a generator for ends but that's apparently just generating little little hints and we need bigger numbers because as we saw in the gilded rose class interesting behavior happens around zero but also around 50 around 11 we need a bit bigger numbers so instead of a completely arbitrary random generator let's make a fish cake or let's make it somewhat smarter generator and again in the gen class there is a utility function called choose and you give it a lower and an upper bounds low and high and for example let's give it minus 50 to 100 so this builds generator that will return numbers in that range so between minus 50 and 100 inclusive that's way more interesting than what we had and now if we rerun this test we should get another diff and hopefully the numbers look better actually they look a lot better yeah let's rerun the coverage report to see how much of the branches were hitting we are hitting 100% of the code branches that's cool so I'm gonna make it a bit smaller smaller data size to make sure and see if we still hit one have a percent you can making it smaller is actually not that interesting I'm just thinking performance wise in a real scenario it might be more interesting to have a smaller data set but as you can see this is not enough so never mind I'm just gonna go back to the thousand size we had to err on the safe side let's rerun the unit test to make sure we have 100% coverage the unit test coverage is at 100% for Gillard Rosie yep and let's approve this file by selecting the contents and pasting it into the golden master file now if we rerun this test it should be green and it should be green every time because we are generated generating deterministic data cool so now in theory we're done we have a regression test net and we can start refactoring and for example if I introduce burg let's say and our space here so this check will start failing if we rerun this global master test you will get a diff saying wow something broke and something broke with the backstage passes item you can see if you start to inspect every red line here it goes wrong on some of the next stage item cases [Music] actually I'm not gonna stop here because it's even confusing to me what's going wrong you don't really know so I'm gonna do one more step let's first make sure we're back into green yep let's do one more step and provide a bit more context in that proofed file because right now we're outputting the results or the end state so in the end we've provided some kind of a tree item and we did the update quality on it and these are the results but we don't kind of know like which test case is triggered this kind of output so let's capture that information as well so we can provide more diagnostics in our go monsters and to do that if we look at how we are approving your just verifying like to string of every item after we have updated the quality you know and let's do it a bit different let's capture the item information before we do any work on it and then do combine it with the item information after so to do that I'm just gonna let's first extract this yeah extract item details so this is the two string of every item after the fact so that's actually let's call it after you know so after cool and let's do exactly the same before we run the code so let's call this before so now we have item details before an item details after and let's combine those into some kind of meaningful texts yeah I'm just gonna hijack this output let's combine these two and how do you combine two lists there's a nice link extension called dot zip you give zip a second list so you give it after and it will do one elements wise pair up of those two lists so it will take the first element of before and the first element of after and you can do stuff with those tuples so for example the first before element first after element what do we want to do we want to print out a string printing out the before and the after on a single line there we go then we wanna so what we have now is a list of strings again containing the before and the after and if we string join those two again move lying so one line per item what's wrong I forgot a quote there we go so now we have desired puts that's saying a bit more let's run approval test again to see if this new code master looks interesting and we have interesting more interesting details namely we have a before age B of quality - 11 and an after and after - 11 that looks really similar to the before doesn't it and actually look at the outputs every before looks exactly an idea after hmm that's not good looks like we're doing something wrong I see already so items we're doing this to string twice but we're not doing it at the moment we expect it dot select is enumerable stuff yeah so it returns an ienumerable and basically that means it's evaluated lazily so not when you do the Select but when you use the Select and we use the Select down here so we're actually not capturing the string representation before how do we force evaluation by calling to lists to make it eager let's do it there as well so now we really have the strings before and we really have the strings after we've combined them and we approve this let's rerun the test to make sure and this this looks better so before age 3 of minus 44 and minus 13 and after the scenario ran we had minus 45 - elf 11 so it looks like something is increasing for everything that's actually correct and we have how much data do we have 600 and 600 plus items so you still have that 100% coverage I'm going to approve this there we go I'm gonna rerun this test to make sure it's green I'm gonna read on it again to make sure it's deterministic and there we go now we have a really good regression net and if we introduce books during your factoring like I'm doing here when you rerun Rakolta math test we get a nice day of saying hey you remember those backstage passes backstage passes of quality 74 and 73 well they used to give quality 48 so they increase in quality but right now it's increasing twice so that's not a three times even that's not what I want so this showing the before and the after integral the Master File is kind of providing more diagnostics while you're troubleshooting behavior so it's a nice way of making it easier to troubleshoot and in the end if you have a rat test and really can't make sense of what is failing there's a really easy fix and it's just ctrl Z and do run your tests to make sure you're green again and try again so this was a goal of master testing using approval tests and F is check for later generation let's do a quick quick summary what did we do today we used approval tests to quickly right call the moss the style regression tests and we made the output or the goal a master file as explanatory self explanatory as possible so we had two before and the after in there to make troubleshooting a failing test much easier next we used FS check data generators to generate a whole lot of random data without having to write a lot of code so let's go back take a look we can generate 100 or 600 items in one two three four lines of code sorry five lines of code so that's pretty nice actually and this F is check library is highly composable if you use that link syntax you can generate generators or you can build generators based on other generators you can nest them as deep as one and if you provide a seed random number generator you can reproduce the results so you have deterministic test a then lastly we used code coverage to check how much of the code we were hitting and if we noticed like we were not hitting 100% of the branches we increased that size parameter parameter sorry parameter we increased that size parameter over here I've ever checked to increase list sizes increase numbers it generated until we had a data set large enough to cover every branch of code if you see like increasing that size is not really helping because the edge case is that specific you can always hard code a really specific item and put it in that list or write a new test for that specific item to get to 100% in realistic legacy code scenarios and that's basically it so this was a approval tests or golda master test using an approval tests and FS check to generate safety net around legacy codes and now you can get started refactoring without looking back over the huge safety net in your back thanks for watching
Info
Channel: Jo Van Eyck
Views: 305
Rating: 5 out of 5
Keywords: programming, refactoring, golden master, unit testing, legacy code, characterization test
Id: _0BFkslU8yM
Channel Id: undefined
Length: 54min 0sec (3240 seconds)
Published: Sun Nov 03 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.