Build invincible integration tests using Cypress and cypress-testing-library

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
well welcome everyone to this special Cyprus webinar it's a little bit unusual because we're not talking to a company was using Cyprus instead we're talking to a superstar awesome developer Roman Sandler hawai Roman hey guys I am doing fantastic thanks for so much for having me I'm so excited for this well thank you for accepting my invitation I have seen a version of this presentation at a conference and I was just blown away how good Roman actually goes through a process of refactoring a long Cyprus test into a really easy to understand and maintain test using Cyprus and Cyprus testing library so Roman do you mind you know telling us a little bit about yourself where you work what's your occupation date today yeah so thanks again as you said my name is Roman Sandler I live in Tel Aviv Israel I am married and have a small child nine month old baby and I work for a company called Fiverr I bet a lot of you know it I work on the front end here at Fiverr doing a lot of cool user interface work and yeah that's that's basically it I love the web I love development I love Cyprus for the passion I've worked the Cyprus for for a few years now and it is honestly the best way that I know how to test you know a web application and yeah that's it that's me Thank You Roman for kind words we definitely love users who love Cyprus I'm Gleb aquata I'm sorry I have not introduced myself I'm vp of engineering at Cyprus and Ramon you said you from Israel from Tel Aviv do you mind going down the slide so we're using a company called Slyder to answer your questions and we can also ask you you know questions like this one if you go to slider calm and enter event code side testing that's where you can answer this all were you joining us from are you in Israel are you in Europe in the United States well I answered in Boston you hi UK ed slider not only you can answer such false but you can also ask your us a question and Roman will answer as many questions at the end so you can also upload other people's questions if you find them interesting will probably go for 40 minute presentation right oh man and then we will have 10-15 minutes to answer your question so definitely go to slider comm enter side testing and you know ask your question there everyone who has registered for this webinar through zoom will get an email where you can take a survey at the end of this webinar if you answer a survey we can send you a Cyprus too short just like this one so definitely don't miss this opportunity this is hot commodity if I understand correctly well Roman no pressure you have audience from around the world why don't we start yeah definitely let's get to it so what is this talk really about then so I think that Cyprus being the the amazing library that it is the however you want to call it right framework tool whatever it is so easy to get started with and be dangerous with and I think a lot of the times you can get to you can write a whole lot of tests that that that potentially give you a lot of value but could also at some point become pretty hard to maintain because there it's so versatile right and there's so many ways you can do so thing so I think it's very easy to do the wrong thing sometimes and this stock is sort of like a summary of my experiences of sort of going through the weeds and and trying to to find the best way to write tests that are really maintainable and to have you know like longevity and really stay for product stay with a product for a long time so this talk is sort of me trying to use the the awesome beautiful library bike and dots called testing library and integrating integrating it with Cypress via this binding called Cypress testing library to refactor a test that's written in a bad way to a good way to a good maintainable sturdy way nice yeah so so that so I just want to say about this this this webinar or this talk that it's sort of not really an introduction to Cypress so I will assume that you you're familiar with like the basic api's and you know what's going on I won't try to sort of explain every every detail so if you do have you know these questions and you're you're sort of having a hard time following along so maybe just let us know in the chat and and we'll try to do our best to to help you out so just a little note about testing libraries so basically as I said kin Dodds started this this library I think initially it was meant for just react I'm not sure though and it was basically it's basically a library that helps you from my eyes it helps you sort of query the dom in this high level abstract way that sort of nudges you to to not test implementation details or a test at a higher level and I think that with time it became this sort of core idea that God that got implemented in a bunch of different bindings to a bunch of different libraries and frameworks so yeah so today we're going to use the the port for Cypress called Cypress testing library and yeah that's it before we go can you go back to the slide and let me switch but Paul - yup next question which is we want to ask you if you're using testing library if you plan to use it or if you tried it and Don I use it so definitely a few winners people want to learn what a Cypress testing library can do that's why they came to this webinar is a Roman but I definitely agree with Cypress testing library and the family of libraries encourage good testing practices and what really really is nice is that once you run both commands like what you'll show the applicable to other libraries in this family so yeah it's very portable knowledge yes yes yes and and I think I think this this sort of this phrase by I think it's by kent saying the more your tests resemble the way your software is used the more confidence they give you really really sums up i think the core philosophy or the guiding principle as they say of this library and and honestly I think this philosophy lends itself so well to Cypress I mean the integration with Cypress feels so natural because because I first test at such a high level I think these two libraries are just match made in heaven yeah yeah can you serve it as a Super Bowl again just to see before we yes are absolutely acts and so definitely the majority of people came to learn what Cyprus testing libraries about so now let's go let's let's dive in everyone so I have I have this we will be using this app called conduit sort of the you know as the playground for this talk and this is actually the react react Redux example of a project called real-world project so basically the concept is developing this app called conduit in all these different frameworks and in libraries just to sort of show how you can create a real-world application and this is really a good example for us to sort of test right so we have this test running here and as you can see we're basically at the home page of this application and we are sort of we see this global feed here right so we have three articles here as you can see each article has its author on top it has a title a description some tags associated to it a like button nothing out of the ordinary and as you can see currently our test is green right so let's let's jump over to views code and and take a look at that test right so this is our test right nothing out of the ordinary and as you can see basically were visiting the route and then we're sort of making these assertions about each article right so this is the first article this is the second article and this is the third article right okay so so this is what's feed page if it shows articles mom by one I mean just a sorting each article in detail in the test after visiting the page exactly and the the data right the data for this test actually comes from a fixture font right so so what you're seeing here the data you're seeing here is is mocked right it's not coming from real API it's coming from a fixture file so let's take a look at that fixture file right so this is this is it this is a JSON that's basically represents a response from this API call and as you can see we have three articles here article 1 article 2 and article 3 and basically our tests right just take some of the values that you see here and make some assertions about things we're looking at in the Dom that are matching the data that's coming from the from the fixture file right so let's sort of let's sort of look at this test right and start and start first of all let's try and think what do we care about at this test right what are we trying to do and I want us to keep that in mind through the whole sort of talk right what is the thing that we care about what are we trying to test so in my mind what we're trying to test we're trying to make sure that the data that is coming back from the server is actually being rendered on the screen right that's what we care about that's like the high-level principle that we need to keep in mind when we are writing our tests so let's switch back to our test and try and and and look at this test here and see what are some of the potential problems here so first thing that comes to mind is that for each article we're super specific about the order ray we're explicitly saying that the you know like the article number you know index 0 is supposed to have this data right but what if you know like what if we go to this JSON file and we take this article and when you put it up here right and we save that rerun our tests it breaks immediately right because because we we we asserted that you know article at index zero has this this in that image but it doesn't anymore because it's a at a different index right so let's let's revert that and see what else we can we can win can come up with right so run our tests again and we're back to we're back to green but another thing that can potentially happen right is what if somebody goes into this test this test file and decided you know what like article one with a number is not good how about we do article one like that right rerun our test it breaks again because we actually sort of hard-coded the the values here right we went here for the for the title here and we hard-coded article one so obviously if something changes in the in the JSON file it it it will definitely it's not reflected in the test but we're gonna ask you a question yeah sure I used I saying but what fixture but you stopped Network request with is it not going to be used from only one test so you can like have one to one relationship right yes yes definitely I'm saying that you know working on Cypress projects I know that in a real world project you would have a lot of mocks and they will be used in a lot of well they would be used in a lot of different places in your application it will definitely be very hard to sort of maintain one-to-one relationship with a mock file right so right so just another thing about this mock file right so let's say like let's say we decide to add another one another article to this JSON file right whatever whatever it's called even if this test would pass right now right it will be a false positive because we have we have another piece of data in our that's rendered on the screen and we are not testing right now because we explicitly just testing those three articles that we're seeing here so let's revert that so I think I think the first problem that we're seeing here is that there's sort of an implicit coupling right an implicit relationship between that fixture file and the test but it's implicit like so I think like the first thing that we can do just sort of work around this is make that relationship explicit right so let's see how let's see how we can do that so I'm just going to copy just everything from article 1 right and I'm just going to delete everything that is not related to article 1 Oh receive a pass test that's it this test is yep yep that's it this test will pass forever and what we're going to do is Cypress provides us with this neat API to sort of grab a fixture file so I'm going to I'm gonna see what that fixture right and then I'm going to specify I want the global feed right I don't actually know if you're you have to put in the extension or not I think you should but I don't remember but it's easy to check right like yep yep so we can we can put Advent here and we will act we will actually get will need to pass a callback here and in the first argument we're going to get our our fixture right so I'm just going to D structure this article's property and I'm going to dump everything that we had from from article one right you're and what well I won't dump it yet what I'm going to do instead of asserting these hard corded corded values I'm going to loop over the articles coming from the fixture right and then for each article I'll use the dynamic data coming from the fixture file right so let's do article articles because it's just JavaScript right you get back an array exactly yeah so we'll do articles for each we'll pass in a callback and then I'm gonna dump out all this code here all right and and actually for each one we'll get an article so this is actually a good opportunity to say that you see this error here saying article implicit he hasn't implicitly has in any type so I'm using types I'm using typescript here which I think works really really well with Cypress and it actually helps a lot with maintaining a test right because I'm going to use a lot of properties from this article inside this test so so type sharp is going to help me make sure I only use what is actually what I actually expect come to come from the server and not make any typos or stuff like that and if if this contract every change is types it's gonna you know yell at me so I'm going to type this with an article interface that I have prepared in advance and actually we will also want to get the index right from the from the second argument which is a number so so first thing we're gonna do you see this index here instead of hard-coding the number we're going to use the index that we got from the loop right so basically right so we want up sorry I goofed it up let's see number right and we are just going to replace all of them replace all of them exactly and we are instead of hard-coding the number we will put in the index there right right so and now it doesn't matter how many articles we have in the fixture file it will always be in sync with what we're trying to test right it doesn't matter if we have four articles or 400 articles and also it doesn't matter what's the order of the articles inside of the fixture file right because it's always mapped to this dynamic index that's coming from data and so everyone can ask just so people understand sure you look at your picture called from file called global feed Jason which is the same future use to stop the route in like in the first route like in beseech yes exactly exactly it's the same file same file here and there right so here I'm going to use the article right and this is actually the string you see here is actually the article the author dot image right and this is actually the article dot authored username and what you see here let me just comment this out right because this is a bit more complicated and we'll come back to this right and this part is the favourites count right so article favorites count and this is the article title so article title and this is the article description so article dot description and I will comment this out too these are the tags we will come back to that because this is also a bit more complicated so let's start off with the date first right so if we go back to the fixture file we see that the date comes back at this format right but what we see being rendered on the screen needs to be in this format right so this is also in my mind this is also a good opportunity to sort of establish the contract between the data right that's that's being loaded into your application and your test and I'm assuming I'm assuming that somewhere in your application code you're already you already have a function or at least an interface right that makes that that transition so if you use it in your application code and in your test code right this sort of in my eyes establishes the the contract in a better way so let's take a look at how that how this might be implemented right so so Cyprus this is a neat little trick right you can access the Cyprus sort of global here and it bundles together a lot of useful libraries and tools such as moment right so I can call moment here I want to pass it the article created app and I want to format it and I have prepared an enum called date formats which has an article preview format right so you can imagine you can imagine yourself doing the same thing and I think this this really creates this sort of nudges you in the direction of creating sort of an abstraction or an interface for this type of thing because it has to live in your application code and in your test code also can you aroma but you're importing this from from the spec file from your actual application always a global but they saw yeah so I am I am importing it perfect just from the Education Code just grab yes currently I'm importing it from the Cypress folder but you can imagine your own applications that it would be imported from your application code somewhere ok yes definitely so moving on to the tags right so when you think about it if the tags right if we look at the fixture file the tags are just an array it's a property that holds an array of Tanks so we can sort of use the same approach that we did up until now right we can do article dot tag list dot for each right NOS in a call back we will get in the first argument will get the tag and in the second argument we'll get a tag sort of index right so I can take just one of these right let's uncomment this and this index here it refers to the article right but this index refers to the tag and the value here can come from this variable right so let's let's try and run the test hopefully we wouldn't get in years let's see oh my god first time first time green so as you can see yeah can you hover over command make sure yes yes so as you can see basically we're doing the exact same thing the exact same assertions that we did before but now everything is dynamic right so let's try and break let's try and break the test in the same way that we did before so let's go to the fixture file right and this changed the order let's put article two first right and we're just going to do this one thing right and as you can see a tests are still green article two is at the top but it doesn't matter right because the index is dynamic all right so let's revert this we don't want to get in trouble here and and take another look at the at the spec file right so sort of I call this like the first step and in in and the refactor and sort of the title I want to give it is use the data right if you are if you are loading in a mock into your test if you have a dependency inside your test on any like data point then make sure that you use it inside of your test and you don't sort of hard code these string values on the assumption that your that your data point will never change right because it will change I guarantee that will change but there is one more thing that we can make better let's see like if if sort of I decide one day that I don't want to have this as an integration test anymore I want to have this as an end-to-end test right I decide I want to run it in my CI CD against like a real a real you know like environment and I decided like I don't want to I don't want to mock this out with a fixture anymore right right we run the test now obviously it breaks right because we're loading actual data from an API now and and it doesn't it doesn't align with the data that we have in our fixture file right all right so to me this is a sign that we were sort of using a too much like a two-level a too low level of an abstraction for for for the way we sort of Express the data loading in our test right because we are very very specific we're saying I want to load a fixture file but what if what if I what if I want to mock out all these API requests using a different tool like Mirage Jas for example right what if I want to make an end-to-end test do I really care does this test really care that we are testing specifically a fixture file no I would argue I would argue that the test doesn't care what the test cares about is the data coming back the data that is being loaded to this screen needs to be rendered on the screen correctly right right so I think that we can use a different function from from Cyprus called weight right and and what we actually want to do here instead of passing in the fixture we want to we want to sort of pass in these this name that we gave it you see see why they're out you know this stuff we're aliasing the request basically right right so the tests PI's on request from the app and then we can spy on that alias exactly so I put in the @ sign here and I'm saying wait for this request to go out and what we will get here is sort of the the full request xhr request right so we want to we want to actually get the articles back from the xhr dot response body right but sort of there's no way for types for it to know that the response body has what's the what's sort of what's the the structure of the response here so we need to tell it what what the structure is right and this is just an interface that I made in advance that tells type ship like what is the structure of of this API request right so once we get the articles back and we save this we run our tests again let's see what we go FOB then xhr get articles right you either white do have get articles twice when you do her out sie route isn't that one get articles the second one is get tags oh you are right kids don't try this at home Wow thank god you're with me glib yeah so basically yeah and there it is the data look and as you can see it doesn't break any more because we are actually we are waiting for this API endpoint we're actually getting real data from a server and and it doesn't matter if we're mocking this out with a fixture file or no so we can Britt bring back the global feed JSON here and you see we're still at green so this is a good refactoring in my eyes and now we're sort of expressing to me we're only expressing the things that we really care about we really care about waiting for the end API endpoint and making sure that it renders on stream correctly alright so let's get let's get to the next thing right so let's library lets you have minutes right yes exactly let's let's get moving here so the next thing that comes to mind right the next thing that that is sort of problematic here is the way we query the dawn right so as you can see here we're using tag names we're using CSS classes right yeah I can was very upset right yes yes and and we are using we're sort of relying on this very very specific Dom structure right so let's let's start using testing library to refactor all of these two to something better right so I'm gonna leave this part at the beginning we'll come back to that let's start off with this image here right so when I think about it I try and think about like how can i express in the in the most abstract right because currently I'm expressing this query in the most literal way I literally want the div with this I mean this is a technically where this is that right I'm I'm trying to think how can i express the this concept right in the most abstract way because I don't care I don't care where this image is right I just care I don't even care if it's an image tag the only thing that I care about is that it's conceptually an image I don't care if it's a div with a background right so testing library actually provides us with a method called find by role right so roles are our super cool part of the browser right where some elements would implicitly get a role and some elements and I mean all elements can get a role using Aria attributes so in this case an image would it would implicitly get the image role right so if I delete all of this right and it's just and I just say find by a role image this will do right and this is a much better expression I think of what I'm actually looking for what are you looking for I'm looking for the image of you know the article author the article author image that's what I'm looking for moving on to the to the next one right so in this case we're looking for the author username so let's sort of open up the implementation here of the article preview and find what we're actually looking for so this is the article author username right here inside of this link right so a a link like an a tag would also implicitly get an enroll right so I do find my role and the role I'm looking for is link right and so let's just let's just keep it in that moving forward so the date let's look at the implementation of the date right so the date here is here right so as so as you can see like a span tag doesn't really have any semantic meaning so there's no it doesn't really there's no really not really a role that we can use here but I think because the the string that we're looking for here is so specific we can just get away with fine by literally the text right we're actually right there all right yes we actually want to look for this text for this piece of text and I'm fairly confident because it's so specific I'm fairly confident that it wouldn't appear twice in the exact same format inside of this article preview right but the assertion here needs to change from should have text who just should exist right I'm just assuring that it needs to exist somewhere in the Dom so let's move on to the next one right so for this one we're looking for the button with the favourites count so we can definitely use a roll here for an by row right and the roll we're looking for is button right and it which is very straightforward and let's look at the and for the for the heading here we can actually look for a role of fine by role ray of heading right and it should have this text and let's take a look at the description and see what else so looking at the description here you see it's just a P tag which is also a tag that doesn't have any any semantic meaning so you know what let's for now just use get by text alright so let's do find my text just pass in description and let's assert that it just should just exist yes that should exist exactly should exist and now looking for for the for the tags here right so weird we can just instead of all of this we can just do like find by role list item right and basically I think that we instead of using a lot of these very specific very literal very low-level queries we sort of opted out to to sort of use these high level abstractions right the the we're looking for an conceptual image we're looking for a conceptual link I don't care if it's an actual link tag or if it's a bun tag right we're looking for this specific text right this is the these are the things that we're looking for and even when you when you read the test I think it reads in a very expressive way but actually this test would fail right now so I will just comment this out and this I think this will be a good segue for us right so let's see the error here right so it's saying found multiple elements with the role list item so so testing library actually sort of tells us if you're looking for multiple items use the variant find all right so the variant exactly there's a variant for each query that is all right if you don't know if you're not looking for a specific one right look for all of them and as you can see we're at green and we're now and we're now you know a lot more expressive a lot more high-level about the way we query the Dom and you know like now for example if we take this this image here for example and we wrap it in a div right which can totally happen when we rerun our tests same thing right because our high-level abstraction doesn't care about the structure of the Dom or what specific target is this could be a div the house you know like a background it doesn't matter right because we are looking for this conceptual thing right and I wanted to leave this sort of article preview to the end to talk about but let's look at the implementation here right so we have this sort of top-level div that sort of is the container for all of this for each article and as you can as you can see it also doesn't have any semantic meaning like we've seen before so there's not really your role we can assign to it there's now and there's no no conceptual you know concept we can use here so for me each time that I want to sort of find these sectioning elements write elements that are used to sort of to sort of in the section what I use is a test ad so essentially instead of using class name CSS class names which are very prone to change I would use a specific data attribute and this is a convention from testing library that sort of just tells everyone hey this is used just for testing please don't touch this right and to sort of indicate what this thing is so this is in our article preview right so we can go ahead and sort of get all of these right everywhere we're referencing the article preview and we can change this get up sorry we can change this get to find by test ID right and we can just delete this div here run our test again all right and now we're running into a problem the same problem as before right it's telling us we found multiple elements with this sort of test ad so one thing that that you can do is sort of give this a unique make this test ID you know have something unique inside of it right so for example you know you can do test article preview and then like let's say like the article oh yeah right and then go to your to your test ID and sort of everywhere that you're using this article preview do do essentially like the same thing right just you look like you know just use the article dot slug and just change this to a template literal right it sounds like you don't want to do that drama yeah I don't want to do that what I want to do instead to sort of avoid you the sort of avoid using you know these super unique test IDs what we can actually do instead of looping over the the data and then looping over you know the Dom elements we can we can reverse that order right so let me just sort of copy all this out of here right and what I'm going to do here is I'm going to use find all by test ID I want to find all the articles and then I want to loop over them right so Cypress gives us this sort of handy each method and this will return a jQuery constructor that has an article preview right and an index now let's just put CY here right and then we can grab all of this again put it inside of this each block and now we can actually you know we can actually sort of wrap this doll article preview right so you're wrapping but jQuery element in object so now you can chain commands and do like find and get and all that exactly right so I'm I'm wrapping it and then I want to add I want to aliasing right so I want to call it let's say like article our article preview right and then basically everywhere that we use every hour that we use fine by test ID like this we can just use CY dot get and just do article preview right but like it seems like unnecessary right because we're getting the same yes yes yes but we will come back we'll come back to that in one moment let me just get the article back for everyone right because we want to see the test still passing so we need the article here it needs to be an article right and what is it it's just the articles in that specific index right and let me just delete the loop that I have here and let's just go over this right because this is a bit a bit confusing but if we find all the test IDs right they have this article preview we're looping over them and then we're getting in the first argument we're getting the jQuery constructor the article preview jQuery constructor and we are wrapping it so we can use Cypress commands off of it right so we Elias it as article preview and then we use it in our tests let's see if we are still a green and we are not right article preview yeah did you change back vets log but you add it yeah let's see I did not August pair programming is the best yes yes right so we are back at green but now we have a little problem with our with our tax right yeah so let's go back to our let's go back to our test here right and sort of you know let's let's just take a look at what we have here right so I'm not expected to find element one but never found it right so we're actually looking here at the we're actually looking here at the what's going on here is that we're trying to use the index right but we don't need the index anymore because we're always we're always in just one article preview right so let's just delete all of these from here and also from here and now I think we can we can be back at green and we are right now so so yeah so now we are are you we're using the test IDs we're looping over them to sort of make these assertions right but we still have a problem with this thing right let's uncomment this out that's just I don't know what we try to do here let's uncomment this out and see why this sort of gives us a problem so let's take a look what happens here so we same time to find out multiple elements with the role link right so what's going on here Cypress all right testing ivory is telling us I found multiple of these and if we look at the implementation we see that we actually have two links here right so maybe we need to use find all but wait I mean how would that even work it wouldn't right right so this sort of leads me to the next step right in the next principle which is you need to be high level you need to be abstract but you also need to be razor-sharp you need to be as as you know as direct as you can to find the element that you're looking for right so let's start off with this image here are we looking for all images for just any image no we're looking for four specifically oh man I'm sorry we're looking for specific for a specific image so sort of these roles have something that's called a displaying name right and a displaying name the default display name for an image is its alt attribute so if we go back to the article preview we see that the alt is article author avatar so if use that we can pass in an options object here and say name right is the article author avatar and the user the the reason I'm using regex here is because I don't care if this is a capital or not I want to I want to be case insensitive right so I'm looking for an image specifically an image that has this name what image are you looking for I'm looking for the article author avatar and I'm expecting it to have this source attribute let's move forward and fix this sort of error that we have here so are we so a link by default its display name is going to be its content right so we can use the article author user name here right so let's say the name is the article author user name and then we're basically we don't need this this assertion or any more we just need exists right and let's see and let's see if this yeah and this solves our problem you see here find biro link and give it the name of user one so it knows to specifically look for that link and ignore the other link so moving forward as I say as I said find by text is specific enough for me we don't need to make it any more specific and the but the button is not specific enough right because we can have multiple buttons on our page a button a buttons default display name is its content but as you can see because the content here as this icon we can't use it so if you assign specifically an aria label this is this becomes the display name of the button of the button role right so if we do name and this is a good practice for accessibility and for yes which is nice yes exactly exactly like this is outside the scope of this sort of talk I'm trying to to focus on maintainability but obviously this type of thing would this type of use would help you sort of make sure your app is more accessible to so we can we can change this this assertion to - excuse me this needs to stay contained because we want to make sure we have the favourites count yeah so find by roll heading though that so the deep so the display name for the heading is going to be its content so we can use the same thing here and say name article title and this should just exist Rahman what do you think about should exist versus should be visible the actual reference I don't I don't have a preference I've always used exist and I think it does the job the only thing that you should not do is is is not have a query is not having assertion a lot of people say like not oh what what does it what does it matter I think because your test would break right if this won't work so the reason you should have an assertion is mainly for me so you can sort of debug it right and understand like what's the problem because this won't actually make an assertion you won't actually see an assertion in your Cyprus console right so all right so it might still fail but you don't see the passing no you don't you don't right so this so you should always make an assertion on top of your query gods right so for this fine by text right with the article description here we sort of have a little bit of a problem because potentially we can have this text I think it's reasonable to think and this happened to me that this text could repeat itself somewhere inside of this article right so one sort of escape hatch that we can use here is to be specific about the selector right so it's not ideal but we can say I want just I want to find specifically a P tag that has this sort of text inside of it so I think this this gets us to to a better place and sort of for this list item let's put this aside for a second and we're back to green right and we are now using these sort of op abstract high-level concept but we are also being razor-sharp in finding our elements so where we are with the time glad do you have any more we are almost out of time we can go over for questions so we'll like you have probably three five minutes all right guys so duration and then we'll take the questions all right so let's try and make this even even better right so let's do let's take a look at the tag so so currently we're just looking for list items right inside of our whole sort of article here so what if we have more than one list right or what if the list has nothing inside of it right so that's that's that's a problem right so one thing that we can do instead of doing it this way is we can actually sort of do the same treatment that we did before and do like then here right excuse me we can use we can use something from Cyprus called within but we're not actually looking for the list item we're looking for the list right we're looking for the list itself and then we want to sort of look inside of it so we pass in a call back right let me just keep this we pass in a call back we get the list in the first argument and we can use we can actually use the list inside of year to make assertions right so first thing we can do is we can say like if article dot tag list right and this is an opportunity to sort of use another goodie from Cyprus you say like if Cyprus underscore is empty oh yeah from low - then we actually expect the list to be empty right but if it isn't then we can do see why yet the article preview here right and find by role the list item this time right and make sure that it should have the text right so basically like we want to get like so we want to find all by role right we want to find all by role basically and we want to loop over them get the tag here and the tag index and then here we want to expect that you have to surround by each arguments tag in tag index right reverend why it's complaining yes so we want to expect that the tag to sort of equal right the the article tag list with the index of tag index right and then we can get rid of this so basic that's look let's take a look at this right we're looking for the list and then within the list right we don't have to we don't actually need this we can just do this right within the list we're checking if it's empty if it isn't you want to assert that it's empty and if it's not empty we want to find all the list items inside of it loop over them and for each one of them I want to expect it to equal its matching you know correspondent in the that comes back from the data right let's see here maybe yeah so we don't want equal maybe to have let's do to contain yeah all right so you see you see equation Roman you text it right but isn't is a conditional testing like if else that goes against the spirit of Cyprus is it I don't know you tell me glib I actually find this is okay because you are going from the data and the data can have empty list or can have tags so you look at the data and say okay it's empty I'll check if DOM is empty oh no it has items I'll check but there are items for each so you going for if-else based on the data but you don't control right in this case I think you're not going from a Dom like if element exists don't click it exactly we we don't query the Dom we sort of use the data to sort of guide us in the in the in the right place and it's all this actually leads us to a more verbose right assertion right because in this case where we do have tags we assert that they contain what we think they should but at this case right we make an assertion that is empty right so that's more powerful one less thing that that I want to do right which is honestly just you know it's just a convenience basically is we can use the same within right right here and then we won't we're positive that everything that we run we actually run inside of the specific article and then we can get rid of all of these balls right yeah we mean is not appreciated yes yes it is it is one of the best functions and so now when we wrap the article previewing we're staying within I can just find the rule find my role and I know that it's looking inside the right article so let's just see and we are back at green so that's basically the whole refactor and I sort of just wanna just let you guys look at it and and sort of think about how much more high-level right how much how how Moore's is you know like how how this test is a lot less brittle a lot less affected by changing your application code in fixture files this test is a lot more sturdy so going back to our little slides here right step one was use the data right always make sure that you are actually using the data that's being loaded step two was query the Dom at the highest level possible and this is where testing library comes in it sort of helps us look at the Dom look at our application from a high level and not from a technical literal sense and step three is narrow your scope right you want to be abstract you want to be high level but you also want to be razor-sharp and you want to go for your elements directly so final advice always optimize for change right your application will keep changing every time your application code we'll keep changing your fixture files will change always think about how resilient your test is to change and that's it Roman thank you for four slides thank you for your factoring can you make sure to make the repo public as well so that people can see so Roman has each step as a separate spec file so you can inspect the tests as they were shown at each step of a journey yeah and definitely follow Roman on Twitter he is an excellent coder and a great human being so definitely follow him thanks thanks a lot yeah please follow me on Twitter and I will definitely make this code public all on github and you can look it up and I would love for each and every one of you to hit me up with questions and things that you liked and you didn't like things that were on you know my DMS are open please please let me know I would love to talk to you guys and sort of share my knowledge really so so hit me up on Twitter or any other platform I'm really happy to just sort of answer any questions I Roman can you go to the next slide yes stop three or four questions and quickly answer them right yes do you wanna how do you keep future files up to date right they will change yes so I want to be honest here I'm of the opinion that you should try and use sort of model factories I'm more of a model factory type of person so I like it when you when your test sort of builds up the world right so you don't have to rely on these fixture files that as you've all probably seen it's sort of hard to maintain so I much prefer using the concept of model factories where you just you let me just spin up an article with the exact structure that I'm looking for but I would say like if you do want to use fixture files maybe have like like I don't know some sort of like a script that that sort of makes sure that they're compliant with an interface or something like that but honestly it's really hard in your opinion what feature could boost ours to get even more testers to give it a try right what's your on your wish list for Cypress Wow yeah so I've had some problems in the past with the concept of moving between tabs okay right moving between tabs and you're in your browser and maybe with I think I had some some issues maybe with copy thanks to the clipboard yeah I like this question do you think Cypress is a good TDD at all I think that it is perfect for TDD because as you can see I think like it allows you to write your tests in an abstract way I don't need to think about implementation I can write it in a high-level like you would you know any using any TDD you know you know when you're testing using TDD which to test a back-end or something right just try and express what you expect to be rendered on the screen and then make the implementation I think Cypress is perfect for TDD perfect perfect perfect for you you know your answer is perfect lots of question if you don't mind because we're out of time which query do you actually prefer yourself Robin I prefer find by rule hands down and actually this is the recommended query by testing library I can maybe link to they have an amazing page called which query should I use and they explained really well also Kent Dodds has a blog post about common mistakes with testing library where he explains why people are not using fine biro more and they should so hands down fine by role I think this needs to be your go-to you can do you saw how you can do almost everything with it right well thank you thanks to everyone who joined us today this was an incredible webinar one of my favorite roman thank you so much for your time thank you thank you thank you guys I had a blast you Cypress it's the best tool around and and thanks thanks again for glad and the Cypress team for having me I really really enjoyed this thank you guys well thank you take care stay safe and healthy everyone thanks guys you too
Info
Channel: Cypress.io
Views: 21,430
Rating: undefined out of 5
Keywords: Cypress, Testing
Id: F8LH9d9eN3M
Channel Id: undefined
Length: 69min 59sec (4199 seconds)
Published: Wed Jul 08 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.