Tj_Vantoll:
Hey, everybody, and welcome to another episode of React Roundup. I am your host today, TJ Van Tol, and with me on the panel, we have Paige Niedringhaus.
Paige_Niedringhaus:
Hey everyone.
Tj_Vantoll:
And our special guest today is Gleb Bamutov. Gleb, welcome to React Roundup.
Gleb_Bahmutov
Hello everyone, thank you for inviting me. I'm not sure how special I am, I'm pretty ordinary.
Tj_Vantoll:
Well, why don't you start by telling people who you are, what you do, and why you're famous?
Gleb_Bahmutov
Or infamous.
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
So I am Gleb Akhmatov. I live in Boston. I've been here for a while. Currently I work at a company called Mercarius. If you want to sell something you no longer use, it's very simple, very good user experience. Before that, people know me from four years working on the Cypress test runner. So if you write end to end, component, unit, API tests using Cypress, you're probably using my code, documentation, plugins. I love writing plugins and open source. Before that, I worked for startups and large companies like MathWorks, but I'm a huge, huge fan of open source work. So I have lots of NPM packages, lots of GitHub repositories and lots of blog posts. And now I got into recording YouTube videos.
Tj_Vantoll:
Oh, nice.
Gleb_Bahmutov
I got myself a professional green screen, so you can find all the little
Tj_Vantoll:
Hehehe
Gleb_Bahmutov
Cypress tips on my YouTube channel.
Paige_Niedringhaus:
We'll have to link to that in show notes for anybody who's interested.
Tj_Vantoll:
So I know we want to talk about some Cypress features, but why don't we start just, we have some beginners that listen to the show. Why don't we start with the absolute basics? Why don't you give like the short version of what is Cypress for people that have never used it, never even heard of it before.
Gleb_Bahmutov
Yeah. So imagine you are a developer and you're writing a piece of code, right? You could be writing a function that adds to numbers. So you write like function add takes arguments and B and gives you a plus B. So you need to make sure that function works. So you feed that function, you call it with arguments, let's say two and three, and you check the result. You expect it to be five. And if it is five and you know, it's working, but imagine you are writing a web application or deploying a website. Well, how would you test that? Well, if you're a human being, you would open your browser, go to the URL, it could be localhost or it could be deployed URL and you see for website loads. And then maybe you click on a button and you check if text changes to what you expected to change. So Cypress is meant to test your website after it has been deployed or running at localhost. So it's not testing a piece of a code like a function, instead it visits the URL. It checks if your loads, you can click on buttons, you can find text, you can kind of interact with a page as if a human user would and confirm that it's working as expected. So it's called end-to-end web test runner because it runs your tests. So that's what it is.
Tj_Vantoll:
Yeah. And I've only recently like the concept of like an end to end tester or runner has been along for quite a while, but I feel like Cypress is one of the, it's at least the most popular tool recently that has made it quite easy to do, at least to me, right? Cause it's some of these tools in the past I've used, like, Oh God. Um, I've used Selenium
Paige_Niedringhaus:
selenium
Tj_Vantoll:
in the past. I've used, uh, like,
Paige_Niedringhaus:
Puppeteer
Tj_Vantoll:
yeah, like all of these tools that like, I have, uh, I don't know, maybe not the greatest relationship with it because they're They're powerful, but they can always be hard to use. Whereas I feel like Cyprus has made your life quite a bit easier for writing these sort of tests, at least from my brief forays with it.
Gleb_Bahmutov
I have to say that's what was my opinion. I did not write Cypress, right? I joined the company very, very early and I used it for a while, for a year before I joined the company. When I saw that, because I went through the same journey, Phantom, JS Casper, all this kind of
Tj_Vantoll:
Yeah,
Gleb_Bahmutov
bridges
Tj_Vantoll:
yep.
Gleb_Bahmutov
towards the browser. And when I saw Cypress API, I was like, oh, just NPM installed and it works.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
And it has time traveling debugger. The API makes sense. It has... you know, all the bundle tools that you need. It records a video of a test run. It's just easy. Like I can concentrate on actually writing a website and it just runs the test. So I don't have to concentrate on the test part as much.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
It just made so much sense. And I do appreciate kind words. It's not the only game in town, obviously, where our testing tools, you know, taking different approaches. I think Cypress takes a nice approach because when it opens a browser, it actually... runs the test in the browser itself, right? So all the commands like visit, click, should be visible, assertions and so on, they execute in the browser, which has some technological advantages over tools that run, let's say, in node and just send commands to the browser, to a remote instance. Because you don't control the browser as much and between the commands, your application might be doing something. So for example, if you say, For example, imagine you're testing an email application. The difficulty with end-to-end tests is that you don't know what's happening in the application. Right? Because it might be written in different framework and so on. So for example, you say, okay, fetch more emails, not images, emails. You wanna click on the button. Well, if you just load the website, it might be fetching the emails at the startup. So if you say, find the button and click on it, well, In between, find the button and click on it, your application might start fetching. And when you try to click, well, the button is disabled, right, by your application. And that's the source of flake, because in between the commands, your web app can actually do something else. Cypress, when it runs in the same browser window, actually runs in the same event loop. So if your application wants to disable the button, while the test finds it and clicks on it, well, the application cannot. because it has to wait for a test code to finish. And when the test code has finished, it knows the button is there, it's enabled, it's clickable. So it kind of removes a large source of this hard to debug flake issues
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
that a lot of tools have. And it
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
kind of makes, for example, debugging the test and the application much simpler. So when I saw that, I had the same experience. It makes my life easier. I want to work on it, I want to use it more. And that's why I joined the company actually.
Tj_Vantoll:
Awesome.
Paige_Niedringhaus:
So one question that I had, Gleb, was recently, I think it was maybe in Cypress 9, there was a new experimental feature that was Cypress Studio. Could you talk, did you have a hand in helping to create that code?
Gleb_Bahmutov
I did have a hand in it, but trying to prevent it from being created.
Tj_Vantoll:
Hey,
Paige_Niedringhaus:
Oh.
Tj_Vantoll:
oh.
Gleb_Bahmutov
I was against it and I'm still am against it and I'll tell you why. So for our listeners, first of all, that tool has been removed and now it's back. Cypress actually removed it in version 10. There was a huge outcry. People were like setting themselves on fire literally in GitHub. Yes. asking for this tool to be brought back and it is back, right? So what it does, imagine you are visiting your website in the browser. And when Cypress has this like special button, you click on it. And now you can just click in your website, find input fields, type, click some more and it's recording your actions. And then it saves it as Cypress commands back in your test file. So that's the Cypress Studio. And this project, I mean, people asking for it, you know, for a while, right. Whereas, you know, other companies would allow you to record your interaction with a website and create a test for it.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
There are a couple of issues that I have with this approach. First approach is that it's easy to record your actions on a website. You know, click on a button, type on an input, click another button, but it's very hard to actually record meaningful assertions. Like what do you expect after you click on a button to happen? Right? I mean, you as a user, you see a text appear, you're like, yeah, I see the text. Fine.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
But if you're recording your action, you have to select that somehow and say, Check that this text appears now. And Cypress Studio had a couple of assertions, like you can right click on an element and say it should be visible after
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
you click the button. But it was very clunky. And after you record this actions, like click, text should be visible, another click, you'd have to save that. Like it saves it into the test file for you, but you'd have to go back and adjust it, like kind
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
of edit, right? Make sure you add, insert meaningful assertions, maybe change some commands and so on around to make it actually stable, solid test.
Paige_Niedringhaus:
Right.
Gleb_Bahmutov
And I always felt that Cypress is actually watching your test file as you code it. And so it reruns the test all the time. If you save a file, I always felt that I would actually write a solid test faster in code, just watching it rerun constantly. Then by recording it and then adjusting it later.
Paige_Niedringhaus:
Mm.
Gleb_Bahmutov
So that was my first. Abjection.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
And you know, people disagree, we can all kind of, it's fine. It's fine. I can see the point that some people can say, Oh, I can record faster than a code. That's fine. But there is another issue that I always found with this recorded test. It's very hard to update them. Right.
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
Imagine you recorded like 50 tests and then. a button can move or the text might change or the flow of the user, like login changes, you have to re-record those 50 tests,
Paige_Niedringhaus:
Yeah.
Gleb_Bahmutov
right? It becomes a huge maintenance burden, right? So I'm glad the Cypress Studio is back because users have been asking for it. I want everyone to kind of check it out, see what we think, see if it works for them. But you know, kind of think about long-term. Do you want to maintain those tests? Are the tests actually... good enough after you record them, or do you have to make a pass over them to make sure
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
they're maintainable in the future? And other tests actually testing what you think they're testing, do they have meaningful assertions
Paige_Niedringhaus:
Mm.
Gleb_Bahmutov
about the application's behavior? So that's Cypress Studio story for me. I was always against it.
Paige_Niedringhaus:
Thanks for watching!
Gleb_Bahmutov
I'm glad that the user find it useful though.
Paige_Niedringhaus:
Yeah, I mean, I've used Cypress Studio when it first came out, and I can agree with you that the way that you interacted with elements could be extremely... I guess it was very specific. Cypress is trying to say, I'm clicking this element, but it made it so specific, or that it was not reusable. So I did find myself either refactoring so that I could use the same thing and just pass in like a different button name or a different element in the browser. And same for assertions, but to me, at least it was kind of like a nice starting point. You know, I at least could go to the page and then I could say, you know, you click on this nav button or you click this footer thing or whatever, and then re kind of rework what Cyprus recorded into a more human readable and friendly manner. But I can see where you're coming from too, where it's just to you it's just a waste of your time and you'd rather just write it out from the start.
Gleb_Bahmutov
I wish there was something like Cypress Copilot, similar to GitHub Copilot, that takes
Paige_Niedringhaus:
Yes.
Gleb_Bahmutov
whatever
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
it recorded and then like, boom! Based on what it learned from good tasks, like adjust it, looks at your application, picks better selectors, adds intelligent assertions, right? Maybe then it would be like, so good, people would be like, glad you were right, but you also were wrong, and it's okay.
Paige_Niedringhaus:
Man,
Tj_Vantoll:
Yeah,
Paige_Niedringhaus:
that
Tj_Vantoll:
no,
Paige_Niedringhaus:
would
Tj_Vantoll:
I,
Paige_Niedringhaus:
really take over.
Tj_Vantoll:
I'm coming
Gleb_Bahmutov
Oh yeah.
Tj_Vantoll:
from pages from pages perspective as well, because not the biggest thing it did for me, speaking of studio is just, it helped me discover how Cypress sort of works because I, and this is just becoming from a beginner Cypress users perspective. But I imagine other people that are new to it would feel similarly, but I can't stare at a test file and they're like, Oh crap. Well, how am I supposed to find that button and how am I supposed to click it? Right. I don't know the API's. Whereas if I can do the click one, I can see like, oh, get an idea of how the tool is approaching it. And then ideally go back and say like, okay, now I know what to do, but I can, the developer in me can say like, okay, well this tool is doing this, which this is a little bit clunky. And if I change this, it's gonna break. So maybe I tweak it a little bit. So it's just a nice, I guess like tool to have in the toolbox and you hope that developers just know how to use it, I guess, responsibly.
Paige_Niedringhaus:
Hehehe
Gleb_Bahmutov
This is such a great point, right? Imagine you are throwing into like new language, new library, new framework, right? How do we build those like initial stepping stones so nobody is frustrated, right? Just like drops their hands, like, I'm not gonna use it. I don't know, I feel stupid using it because I don't know what's happening and just gives you enough information. So you're like, oh, I see how it's working. Okay, it's not too scary. And this is the next step I can like. make it better, add one more command. I know where to find documentation for commands, right? And if I, for example, use command click, where they generate for me, it leads me to double click and maybe click on the top corner, right? Of the element instead of a center. And maybe leads me to, you know, how to check if a button is visible before I click, for example, right? Like
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
all these extra things, like, this is not, it could be a nice pathway. to realistic tests. Yes.
Paige_Niedringhaus:
Mm-hmm. Yeah,
Tj_Vantoll:
Yeah,
Paige_Niedringhaus:
so, oh, go ahead, TJ.
Tj_Vantoll:
it reminds me of like UI builders for like the web. It's like, it's a great starting point. Like does it produce stuff that's a little bit clunky and hard to maintain? Sure, but is it a great tool for developers, for beginners to like learn the platform a bit and to build something like actually useful? Yeah,
Paige_Niedringhaus:
Mm-hmm.
Tj_Vantoll:
that too.
Gleb_Bahmutov
Yeah.
Paige_Niedringhaus:
Yeah.
Gleb_Bahmutov
The one thing about testing tools, remember you have kind of like double audience. You have the developers, right? They're working on the web application and testing it. And you also have maybe a quality assurance department that takes a view of like, there's a feature we need to make sure it works. So they start writing from completely different viewpoint from developers. And the developers have a huge advantage. If a Cypress Studio gives them a selector to the bottom, that's like really clunky, kind of look like position, subclass, like really, really unmaintainable. They can change it. They can add a test attribute. They can use ARIA label. Whereas QA, when they come in and they're like, okay, I need a test for this button. They only have to work with what's available, right?
Tj_Vantoll:
Yeah.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
And there's always like which. kind of audience do you optimize it for? Sometimes it's impossible.
Tj_Vantoll:
Somebody have a Formula One car drive by their house there. That was... Yeah. It's... It's... It's... It's...
Gleb_Bahmutov
It sounded like one, right? And I
Tj_Vantoll:
It's...
Gleb_Bahmutov
live on
Tj_Vantoll:
It's...
Gleb_Bahmutov
a small street, so someone definitely breaks a speed limit there.
Paige_Niedringhaus:
So we know that Cypress started out and has done extremely well as an end-to-end testing framework. And I have to say that in more recent versions, one of the cool things when you first install it is all of the example end-to-end tests that you get. So if you're, like TJ said, if you're new to it, you can see in action all these various things that you can do with Cypress, but. One of the more recent additions, it seems like, is the ability to do unit testing or to do component testing. So maybe you could tell us a little bit more about that because I've seen that it's a possibility, but I really haven't looked into the specifics of it yet.
Gleb_Bahmutov
Thank you, Paige, for bringing it up. I mean, we talked about this before the show, but I'm glad you brought it up. Imagine you are testing a complete website, right? This is what Cypress does. It's end-to-end. You visit the URL and you interact. You have no idea what the framework or implementation details are, but that's not how you actually write the website or web application, right? You're probably working with individual parts in your framework. It could be React. could be Angular, Vue, Svelte. You could have your own homegrown components and framework and libraries. So for example, let's say you want to make sure that the date picker that you work months on or that you brought from some kind of UI or material UI library, but actually works and works for all the different edge cases where some dates are unavailable. How does that look? So it becomes really hard to actually test it through end-to-end tests because you have to control the data. And Cypress can do some of it and it can control the clock, but it's, it's really slow and clunky process to show the date picker and all the different configurations. That's why people use Storybook. They take the component, they pass different props and they see how the component looks in all the different situations. So maybe four years ago, I had this idea that What's the difference between a component and the web application? Very little, right? You can think of your component running by itself as like mini web application. In most cases, if you have a date picker component, you just need react library, maybe set up some props and put your date picker component at the root of your application. You can literally change your public index HTML to instead of the app to mount. just the date picker and a lot of people, that's how they develop, right? They have this like development index HTML file where they just, whenever they need a component, they just change the text and mount that component and look at that in a browser and I know react scripts like bundles everything up for them. Okay. Great. So why can Cypress do that? So I've written adapters for each framework, including react, where you say import the component. And then you have mount command and it literally takes your component, creates like a dummy page for you all behind the scene and bundles everything up and starts that react component like date picker as a mini web application by itself. Okay. And once the web component, or not like once your framework component starts running like date picker, after that, it's a full fledged web application. You can use any Cypress command like Find the button on the date picker, click on it, check the text is visible or some date is disabled. That's it. So you just have to mount using framework specific code and after that you use just end to end test commands. So I've written components for every framework and it took a while to actually make it a first class citizen in Cypress because you have to think about. How do users actually use that? How do you integrate with all different frameworks and bundlers like VIT and Webpack and whatever people want to use?
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
What's the API would be? So right now Cypress has it for React. They had it for a while. They released it for Angular, Svelte and Vue. And I even released a course, Cypress version 10 fundamentals. It's a free course on BlazeMetal University. we can link it in the show notes, where I showed a Sudoku game. And I said, okay, this is how you write end-to-end tests. And now let's look at React component tests. So one of the components could be a timer, right? That just clicks
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
every second and shows how long you've been solving the Sudoku. So you just mount that component by itself and you check with Cypress commands, but after one second, it shows 0001, after two seconds, so it ticks. Another component was like the status, where it shows the difficulty of the game, the current mode. Another component could be like the numbers that you select. And think about your entire application. It's actually a tree of components. You kind of create a footer out of individual components. You create navigation. You create maybe something else. In the case of Sudoku, you can think of the root being this big... game component and Cypress component testing allows you to mount small components and then bigger components all the way to the game component at the root. Right. But you're not visiting by URL, right? You just mounted component. You can pass the props like normally, right? You can pass Cypress spy and stops, right? And, and when you interact with the component, you can check that, that game component actually, for example, changes the provider data correctly.
Paige_Niedringhaus:
Yeah.
Gleb_Bahmutov
So you test that component already with its implementation details a little bit, but not to implementation specific, right?
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
You still see it running and so on. So super happy. Very little framework specific knowledge is necessary. You know, once you've seen it in Reactor, you can use the same approach in Vue, Angular, right? And you don't have to learn any specific or framework specific tooling. Right? You can use React testing library, but instead of using it at like just level, you would use Cypress testing library with all your Cypress commands that are equivalent, like find by label, find by role, right? So you can transfer and then you can use the same knowledge. If you, for example, have to work with a view application, it's literally
Paige_Niedringhaus:
Mm.
Gleb_Bahmutov
just a mount command. You know, details might be a little bit different, but the rest of the test is the same, so no more, you know, view testing. no more angular test harnesses. It's just like universal way to mount something and then go. You understand the rest of the test. It's all the same. So it's out there. Try it out. Let me know how it works for you.
Tj_Vantoll:
Man, Angular test harness brings back some memories and they're not very good ones. So.
Gleb_Bahmutov
You know the funny thing, but Cypress component testing for Angular actually wraps around it. So you have all the power if you need to, right? Of test hardness and test
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
bed, right? It just, it's hidden for you by default. You just see that component also unlike boom appears on the page and it functions and it works. Right. But after that, you don't have to like trigger digest cycles or any frictional specific, it's all taken care of for you. You just click on the button, check what something appears. or network call is made and so on.
Tj_Vantoll:
Yeah, this is, it's sort of fascinating to me because it's almost like a different way of approaching the same problem we've been doing forever. Cause it's, in a way it's very similar to testing library, at least like to me it sounds very similar, but I suppose I will really, I'm kind of curious on the difference. Cause it seems to me the bigger thing is that it's running in an actual
Gleb_Bahmutov
Yes.
Tj_Vantoll:
browser, right? So I'm gonna guess there's just some benefits to doing that. Like it just feels like Cause even like testing library encourages you to think like you're using a browser, but it's, it seems like this would be a step further because you literally are using a browser. So you sort of very much have to, to, to code up your tests as the component would be used. Am I, am I thinking of this right?
Gleb_Bahmutov
No, you're absolutely correct. So if you think about React Testing Library and your component, you would actually use Jest. Right? So the Jest is the test runner
Tj_Vantoll:
Yeah,
Gleb_Bahmutov
and
Tj_Vantoll:
okay.
Gleb_Bahmutov
it has a JavaScript DOM emulation, Jest DOM, right? Under
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
the hood. So when you use React Testing Library, it mounts your component inside the synthetic browser environment, but it's nothing like a real browser. It just has like something that looks like API. And then you would use React Testing Library to fire all these like synthetic events, like click, right?
Tj_Vantoll:
Yeah,
Gleb_Bahmutov
And then check
Tj_Vantoll:
yep.
Gleb_Bahmutov
what something happens, right? All that goes away with Cypress component testing. Cypress starts a browser that it controls. It bundles everything up using your framework of choice. And then it mounts the component and let the browser actually be the browser. And when, for example, you want to click, you don't have to create synthetic click, right? It clicks using the browser. It uses either a real click, like a native event or synthetic, but it doesn't matter. It's a real thing after a while. So you see everything in the browser. It behaves correctly. Whereas there's a lot of things that just DOM doesn't give you in terms of API. And what it gives to you might be actually different from what a real browser would do. Thing like cursor events, touch events, all different kind of quirks of just DOM compared to the quirks in a real browser.
Paige_Niedringhaus:
Yeah. So one question that I have that's kind of along those same lines is when you're writing component tests, is it the same as if you were writing end-to-ends where you can actually open up a browser window and see your component and debug it? Because that's, I mean, that's one of the most helpful things about Cypress is that I can actually see what's happening. It doesn't have to run headless. And that's one of the most frustrating things about React testing libraries. It prints out this awful HTML
Tj_Vantoll:
and
Paige_Niedringhaus:
in the console and you have to try and figure out what's missing or what's different.
Tj_Vantoll:
or yeah,
Gleb_Bahmutov
It's,
Tj_Vantoll:
or why
Gleb_Bahmutov
yeah.
Tj_Vantoll:
couldn't it find my compo like, you know, why couldn't
Paige_Niedringhaus:
Right.
Tj_Vantoll:
it find it? It looks like it's right there.
Paige_Niedringhaus:
Yeah.
Tj_Vantoll:
Cause I, cause with Cypress, the other thing too is the recordings sometimes. Cause for
Paige_Niedringhaus:
Mmm.
Tj_Vantoll:
people that don't know Cypress will basically record what it's doing in the browser. And sometimes that can be absolutely invaluable for debugging because sometimes you're like, why can't it find it? And then you look at the recording and you say like, oh, because the button's not there. Well, wait, crap. What went wrong that it's not there, right? Whereas if you're looking at as Paige said, if you're looking at just some dom dom, sometimes that stuff is way harder to track down.
Gleb_Bahmutov
Yeah, you're absolutely right. So Cypress, when it runs component test, opens the real browser, just like end-to-end test. You see it, you see the actual test on the left and the commands, you see the actual component running in the real browser, you can open DevTools, you can install React DevTools. And I think even for React, it actually comes built in already with Cypress component testing, so you can find the components and so on. Now, the only thing that where you... have to install anything extra like as a plugin or like my code is that if you want, for example, to access the internals of your component in React, right? Like you want to, for example, change the state. Now, those are implementation details. And in reality, even if you write React Cypress component as you shouldn't do that, right, you should think of your component as a black box, you interact with that component it's on a page like a real user, right? Like, for example, you can click on. Well, mount your date picker and see if a date is disabled because that's the prop you send, but you shouldn't kind of reach into the component state and say it has state disabled kind of property.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
You shouldn't do that. It ties your task too much to implementation details, but you could, but you see your component, you can inspect the DOM elements, you can see the network calls, you can stop and spy on them as well from your task, right? But it's a huge advantage. because you see what's going on. You can not only see a video of your test run or screenshot, but you have time traveling debugger where you can see how your component looked at each step of your component test. You can just hover over the step.
Tj_Vantoll:
Yeah, it sounds to me a little bit like, um, to, to keep comparing it to the things that are out there a little bit like storybook, but they're like actual automated tests, cause I think a lot of people use storybook for here's my component and here's like the 10 ways you can use it, but that's not automated that like, if you're actually using it for like QA or testing purposes, you have to send someone in there and who's physically clicking the things and ensuring
Paige_Niedringhaus:
Hehehe
Tj_Vantoll:
it, whereas this is like. recognizing different component testing scenarios and just automating that they do what they're supposed to do.
Gleb_Bahmutov
Yeah, you're absolutely right. And speaking of Storybook, about a year, they actually started like adding commands to their stories, I believe, where you can mount a component and then like click on a button, right? So they're kind of trying to introduce this test concept where you interact and maybe see it, right? But compared to where Cypress is with its API and test running capabilities where you can control the clock, control the network, control everything in the browser, right? It's like one 20th, right? Storybook
Paige_Niedringhaus:
Yeah.
Gleb_Bahmutov
is really optimized to like be almost like a catalog or an Atlas of your components rather than like, I'm going to
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
functionally exercise my component and make sure it does what it's supposed to do rather
Paige_Niedringhaus:
Right.
Gleb_Bahmutov
than this is how it looks. This is how, you know, all the props are.
Paige_Niedringhaus:
Yeah. So one question that I had for the component testing is how does it stack up in terms of the amount of time it takes to run the tests? Because that's one of the things that was nice about Jest is that it is so fast with running unit tests and integration tests and end-to-end tests traditionally just take longer because it's interacting with a real DOM. So how did the component tests do in terms of time?
Gleb_Bahmutov
The end-to-end tests are slower than unit
Paige_Niedringhaus:
Sure. Right.
Gleb_Bahmutov
tests,
Paige_Niedringhaus:
So, I'm going
Gleb_Bahmutov
right?
Paige_Niedringhaus:
to go ahead
Gleb_Bahmutov
That's
Paige_Niedringhaus:
and
Gleb_Bahmutov
by
Paige_Niedringhaus:
start with
Gleb_Bahmutov
default,
Paige_Niedringhaus:
the first one. So,
Gleb_Bahmutov
right?
Paige_Niedringhaus:
I'm going
Gleb_Bahmutov
You
Paige_Niedringhaus:
to go ahead
Gleb_Bahmutov
open
Paige_Niedringhaus:
and start
Gleb_Bahmutov
the real
Paige_Niedringhaus:
with
Gleb_Bahmutov
browser and it actually runs at the speed of your website,
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
right? That's the end-to-end test. The web components, once the browser is open, run as fast as just test. Because I understand it's a real browser, real APIs are involved, right? But the component tests, they are mounted very differently. They don't reset everything like end-to-end tests in Cypress. They can share the same browser's window. So they run extremely fast. And every time you change something in your source code or your spec files, because it's the same bundle, Cypress reruns everything affected. And they're flying, to be honest. But there's only the initial open browser, let's say 10, 20 seconds on your machine. That's the slow part.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
After that, my tests are super fast. And to me, this initial penalty for opening a browser, you only pay it once. Imagine you come to work, right? You start your VS code. You don't close your VS code after you work with a file and then, okay, I need to open that file, close it, restart it, right? But no, so the same thing with Cypress. You keep your VS code open while you editing the code and you keep Cypress just running on another screen, watching your files. Right. Never like it never has to reopen the windows. Right. So you don't pay that penalty for each test and on CI this initial kind of penalty for starting the Cypress run. I guess 10, 15 seconds, but it's CI, right?
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
It probably takes longer for you to install the dependencies, check out code, right, prepare the Docker image. Right. Actually start your application if you want to run end to end test. So to me. The component tests are pretty much the same speed as just test, right? But they do the real thing, which is
Paige_Niedringhaus:
Yeah.
Gleb_Bahmutov
nice.
Tj_Vantoll:
So what is the status of the feature then right now? Is this like, I should be using this in my production apps immediately? Is it, I should be just sort of toying around with it, seeing if it's a good fit for me? Where is all that at?
Gleb_Bahmutov
I always said it was ready from day one. Four years ago when I released it as like a plugin for Cypress, right, something you install separately, you could use it, right, and use it successfully. You don't use it in production. That's the big thing, right? You use it as a dev dependency.
Tj_Vantoll:
True.
Gleb_Bahmutov
So,
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
right, if it doesn't work, you just don't use it, right? Or you don't write the test. If the test like locks up, right? Or doesn't do the same thing, you just skip it and you file a bug with Cypress. And if you can create a reproducible example, right? Then the Cypress team will definitely like fix it right away for you. Other people, and I've done it myself long time ago, but other people now like took all the React examples from testing library, you know, can see that's books and courses, you know, and so on, and they recreated them one to one. So my friend Murat Oskan, he is preparing to release it. I mean, the repo is public already where he has hundreds of test examples. In React testing and so on and equivalent Cypress component tests.
Paige_Niedringhaus:
Nice.
Gleb_Bahmutov
They all do the same thing, they are much shorter because the API is simpler. They all work. I don't see any major issues. The only thing that is, I would say, it's kind of complicated right now and just gives you by default is code coverage
Paige_Niedringhaus:
Yes.
Gleb_Bahmutov
and stopping the imports. So
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
By default, Jest has this thing where you can instrument your code with counters. And at the end of a test run can say this line in your source file, in your component was a test run 10 times. This one five, but this one never was executed. So you probably should add a test to cover this.
Paige_Niedringhaus:
Right.
Gleb_Bahmutov
So in Cypress is possible in my course, I show how to do that. You add one more bubble, Istanbul plugin. And then Cypress has a code coverage plugin that generates the reports. So it's possible, but it's something you have to add and Jest has it out of the box. And Jest is also running, because it loads everything, it can stop your import. So when you write a component test, you can say, well, this component is loading this other component, but I don't wanna use it. So why don't you substitute the smoke function,
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
right? So Cypress has it, but you have to actually kind of write webpack yourself. I do have examples, but I wish those two things were simpler. Now, the advantage with Cypress is that if you can configure, for example, code coverage for your components, you can also configure it for end-to-end. And Cypress plugin will combine it for you. And you'll just hit your numbers like right away, because end-to-end tests are so efficient
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
at covering majority of your code, even with simple tests. So it will be very efficient more than, but most of the things are the only thing where like, I'm kind of say they're nice to have,
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
but even without them, it's fine to use.
Paige_Niedringhaus:
Yeah.
Tj_Vantoll:
Do people tend to then, if you fully buy into this approach, like you've drank the Cypress Kool-Aid, you're going all in, would you have like one test suite that did it all, like run your end-to-end tests and run your component tests? Maybe you'd like block it up, so like maybe during the development, you could run like isolated components, but your like CI server would just presumably run them all at once, right? Cause they're all just Cypress tests at the end of the day, right?
Gleb_Bahmutov
Yeah, so here's my approach and you can disagree, but I would keep all your tests in the same repository with your code, first of all. Now, Cypress would keep the end-to-end test by default in like cypress slash e2e folder. So they're a little bit separate from your source code but usually is in source subfolder. The component tests they advocate is to put right next to your source code. So in your source folder, you would have like tape picker that I know. And you would have date picker.psi.tsx that has component tests for this. So you have it all together. Now let's say you open a pull request, your CI should run all the tests. Like I am a strong advocate, run all the tests. You probably want to run component tests first because they are faster. Right? You don't have to even bundle or start application. So if your Cypress component tests pass, then the second command would say run. Or like start your application locally, run end-to-end test against it. And then if both pass, then you have high confidence that you can merge this pull request and so on. But
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
yeah, run them all. Run them all the
Tj_Vantoll:
Yeah.
Gleb_Bahmutov
time, but let the CI do it. Don't run all the tests. It's so easy to write a lot of end-to-end tests that they take five, 10 minutes, half an hour, an hour. Don't do it yourself. That's what CI machines
Tj_Vantoll:
Hehehehe
Gleb_Bahmutov
are for. you know, spin up 10 machines, let you know, use cyber spiralization, whatever else tools to split it up across all the end to end aspect, and let your CI do like the boring work of like going through all the end to end tests for you.
Paige_Niedringhaus:
Yeah.
Tj_Vantoll:
I think your advice is great. And I think that's a structure that a lot of people are using today. I know Paige and I have a structure that's similar to that. I think,
Paige_Niedringhaus:
Mm-hmm.
Tj_Vantoll:
I think the one big difference though, is that today, lots of times those co those approaches are written using two different tech stacks, right? So I have my Cypress or my end to end tests or whatever. And then I have my like either unit tests or component tests or whatever. That's used, that's written using completely separate tools. So. I think one big advantage that I haven't been giving enough thought up until now is that if you're consolidating on one set of APIs that just makes sure, I don't know, the amount of like mind shift you have to do between the two, there's like one less thing to learn, right?
Paige_Niedringhaus:
Mm-hmm.
Tj_Vantoll:
Because someone like I, I'm a very casual React developer overall. And when I jump into these environments, I'm always like, oh God, how did I, how do I select an element in React testing library? And then I go to write the end to end test and it's like, oh man, now I have to figure out how to select a button in this thing. And so I'm back to like the same stack overflow posts. And I feel like doing them once just the fewer moving pieces and dependencies you can have in your apps, usually the happier you are.
Paige_Niedringhaus:
Mm-hmm, the less
Gleb_Bahmutov
This is
Paige_Niedringhaus:
NPM
Gleb_Bahmutov
a huge,
Paige_Niedringhaus:
libraries.
Gleb_Bahmutov
this is absolutely incredible bonus point, right? It's a single stack, right? So all the tests for code that's meant to run in the browser can be written using one tool, right? Cypress. If you have code that's meant to run in node, well, Cypress doesn't run a node. Okay. That's the only place where you probably will have to bring another technology stack, right? Maybe Ava, Mocha, Jess. Right. You name it. Now, Node has a built-in test library, right? Or test runner, right? Like we've Node 17, they have their own Assort and the test runner. So you don't even have to bring a separate tool for your Node code. All right. But Cypress can easily take over entire front-end testing. And one more thing that, you know, I always use, Cypress can run API tests for you. Right. So usually people bring one more tool. to, for example, hit the REST API endpoint, right? Kind of confirm the server is doing, maybe GraphQL endpoints. Cypress can do that for you, right? It has Cyrequest command that can execute any kind of HTTP call. You can check the results. And I have a plugin called CyAPI that actually takes those calls, like requests and responses, and puts it right in the browser. So you see what's happening, right? So you can actually visually see. each step of your test and what the server returned.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
So if you do API testing, you can use Cypress as well and cover the whole gamut of testing.
Paige_Niedringhaus:
Man, Cyprus is the one tool for everything apparently.
Tj_Vantoll:
Yeah, dude.
Gleb_Bahmutov
Hey, that's why Tolkien called it one tool to rule them all. Am I paraphrasing? I forgot
Tj_Vantoll:
Yeah,
Gleb_Bahmutov
how exact quote goes.
Tj_Vantoll:
he was famously
Paige_Niedringhaus:
Close.
Tj_Vantoll:
a Cyprus fan, so
Paige_Niedringhaus:
Right?
Tj_Vantoll:
I think it makes sense.
Gleb_Bahmutov
He loves trees, so he might be.
Tj_Vantoll:
So.
Paige_Niedringhaus:
So what would you, what kind of advice would you give to people who were interested in getting started either with Cypress end-to-ends or components? Is there one that you would recommend they start with or are there any strategies that you have for component testing like going from small to large or vice versa?
Gleb_Bahmutov
For anyone just starting and like trying to see what the Cypress thing is about, look at Cypress documentation. They have very nice introduction and examples, right? I would say start with end-to-end test because you don't need to know anything about the website to actually write end-to-end test. You just need to say, okay, I want to test this URL. I didn't deploy it. I don't know how it's written, but I just want to visit this, I don't know, todo mvc.acma.co, right?
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
And you can write the first Cypress. test which just says, SciVisit, you know, to do MVC.ACMA. And that's it, and see how it runs. So you don't need to know anything about the application. If you wanna learn about component testing then, well, in that case, you actually need the component source code, right? And you can use Cypress examples as a starting point, but you probably are interested more at your own companies or your own open source projects source code so that you can... start Cypress there. And I would say if you're already using Cypress on your project, that's the sweet spot, right? If you already have end-to-end tests and you know how they run, you can say, okay, now let me configure component testing point at whatever framework I'm using locally.
Paige_Niedringhaus:
Mm-hmm.
Gleb_Bahmutov
And now let me write a test that mounts a date picker and now tries to test it. So start with end-to-end and then kind of go down the pyramid to component testing and maybe like you need API testing.
Paige_Niedringhaus:
got it.
Tj_Vantoll:
Well, glad this has been awesome. Are there any things Cypress related that we have not touched on? Like any tips you wanna give people, any other features or any topics that we've missed that you wanna drop?
Gleb_Bahmutov
No, but in the peaks, it's funny how you said any Cypress tips. So I have a website called cypress.tips where I just post, you know, all everything I do. Cypress.tips if you want to find my tips.
Tj_Vantoll:
That's an amazing URL.
Gleb_Bahmutov
That domain, I mean, I love a lot of testing tools, right? So just in case, I also got Playwright.tips, just to see how
Tj_Vantoll:
Heheheheheheh!
Gleb_Bahmutov
this thing turns out.
Paige_Niedringhaus:
Nice.
Gleb_Bahmutov
So it's, you know, look at those unusual top-level domains. You can find lots of interesting things. Like I did find Gleb.dev, that's my, you know, top domain that redirects to my website. So it's available.
Tj_Vantoll:
Very cool. Well, why don't we move on to our picks? So we picked something from either around the tech world, music, TV, something around our lives. And Paige, do you want to kick us off today?
Paige_Niedringhaus:
Sure, so I will keep the kitchen utensils and kitchen tools train rolling since we seem to have at least one of those every week during picks. My pick this week is going to be a three pack of kitchen tongs that you can get on Amazon for very inexpensively. The nice thing about them though is that it comes in three different sizes, so when you've got your big steak that's on the grill or you've got a small potato that you need to turn over in the oven or whatever. there is a tong that is the right size and you know you can use all three at the same time if you want to. So that's going to be my my pick for this week.
Tj_Vantoll:
I love it. Longtime listeners of the show are gonna have like a full kitchen set up by the time
Paige_Niedringhaus:
I
Tj_Vantoll:
we're
Paige_Niedringhaus:
know.
Tj_Vantoll:
done with this.
Paige_Niedringhaus:
I know.
Tj_Vantoll:
So I'll keep the sort of at least food thing related going, theme going, I'm gonna pick HelloFresh, which is one of the many like meal delivery services. I might've picked it before a few years ago, but we've been using it for a long time now. And it's, there's a lot of these concepts out there, but basically they ship you food every week. Uh, and I think I'll pick them because they're, their app has gotten quite good that you now have a lot of choices for meals. They make it easy. Like if you're going to be gone or just don't want food for a few weeks, it's easy to pause it, it's easy to add extra meals. Um, they've done a lot in terms of improving the process. So it feels pretty slick to use and. Food's pretty good. I like it because I like to cook, but I hate to shop for like individual ingredients. or like buy a thing of some spice that I'm only gonna use for one thing ever, then it's gonna sit in my cabinet for years. So HelloFresh is really good for that. So if you've ever thought about one of those services, it's pretty good.
Paige_Niedringhaus:
I've tried those in the past and I really like that they give you recipes because it makes me try things that I would never have thought of or found on my own.
Tj_Vantoll:
Yep. And also makes our kids try things that they would have never tried on their own. That's a nice, it's either a
Paige_Niedringhaus:
bonus.
Tj_Vantoll:
benefit or a curse, I guess, depending on how you look at it. Gleb, what picks do you have for us?
Gleb_Bahmutov
Well, for anyone who wants to try Cypress, learn about it, cypress.tips.com slash courses. I have a free course about Cypress 10, covers React, end-to-end and component testing. I also will do a workshop that's free. You're encouraged to donate. It's hosted by Source Labs. It's called Testing for Good, right? We'll put the link in the show notes. And all proceeds from donations are going to a climate organization. As you- probably know, we broke the planet's climate by emitting so much greenhouse gases that is actually affecting the temperature and hurricanes and droughts and wildfires. So my last peak is an organization called 350.org. And 350 is the safe number of parts per million of carbon dioxide. Right now we're at 420 approximately, and it keeps increasing. So the 350 has been very effective. at trying to maybe stop the climate change and reverse it. So I encourage everyone to find your local chapter, join it locally and act together to maybe make the climate crisis slightly less scary.
Tj_Vantoll:
Awesome. Could
Paige_Niedringhaus:
Nice.
Tj_Vantoll:
you spell that for me just so, or for our listeners? Because I'm trying to Google in the background and I couldn't find the right domain.
Gleb_Bahmutov
It's 350, like the numbers, 350.org.
Tj_Vantoll:
Oh,
Paige_Niedringhaus:
got it.
Tj_Vantoll:
okay.
Gleb_Bahmutov
They use the number, which is another kind of tip if you need a domain, just get
Tj_Vantoll:
That's,
Gleb_Bahmutov
a number.
Paige_Niedringhaus:
Numbers.
Tj_Vantoll:
I totally was like, I couldn't find it because I didn't use the number, but man, people aren't gonna need the show notes because all the URLs you're dropping are like, it tops like seven characters.
Gleb_Bahmutov
It's so difficult to, you know, like as a developer, you have to have at least 10, 20 domain names that you're
Paige_Niedringhaus:
Right.
Tj_Vantoll:
Hehehehe
Gleb_Bahmutov
not using, but you just like thought
Paige_Niedringhaus:
Hold
Gleb_Bahmutov
it
Paige_Niedringhaus:
on
Gleb_Bahmutov
would
Paige_Niedringhaus:
to.
Gleb_Bahmutov
be a great idea. Yeah. So sometimes you, you know, you find excellent names.
Tj_Vantoll:
Awesome stuff, Cliff. This has been a lot of fun. My last question for you, if people wanna follow you or keep, is there like a good social place, where should people check you out?
Gleb_Bahmutov
Absolutely. So it's my last name, bakhmatov, B-A-H-M-U-T-O-V. I have Twitter handle. It's LinkedIn. It's GitHub profile. I would say it's easier probably to remember gleb.dev, G-L-E-B.dev domain. That will have links to all my social. But
Tj_Vantoll:
Perfect.
Gleb_Bahmutov
tweet at me, and I'll tweet back.
Tj_Vantoll:
Excellent.
Paige_Niedringhaus:
Perfect.
Tj_Vantoll:
Well, this has been awesome. I learned a ton about Cypress and Cypress component testing, so hopefully other people have as well. Thanks so much.
Gleb_Bahmutov
Thank you, Page and TJ. Thank you for listening.
Tj_Vantoll:
Cool. All right, everybody, until next week.
Paige_Niedringhaus:
See you then.