Kent C. Dodds
Kent C. Dodds
Kent C. Dodds is a world renowned speaker, teacher, and trainer and he's actively involved in the open source community as a maintainer and contributor of hundreds of popular npm packages. He is the creator of EpicReact.Dev and TestingJavaScript.com. He's an instructor on egghead.io and Frontend Masters. He's also a Google Developer Expert. Kent is happily married and the father of four kids. He likes his family, code, JavaScript, and Remix.
Full Stack Components
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
by

Remix Fundamentals
React Summit 2022React Summit 2022
136 min
Remix Fundamentals
Workshop Free
Building modern web applications is riddled with complexity And that's only if you bother to deal with the problems
Tired of wiring up onSubmit to backend APIs and making sure your client-side cache stays up-to-date? Wouldn't it be cool to be able to use the global nature of CSS to your benefit, rather than find tools or conventions to avoid or work around it? And how would you like nested layouts with intelligent and performance optimized data management that just works™?
Remix solves some of these problems, and completely eliminates the rest. You don't even have to think about server cache management or global CSS namespace clashes. It's not that Remix has APIs to avoid these problems, they simply don't exist when you're using Remix. Oh, and you don't need that huge complex graphql client when you're using Remix. They've got you covered. Ready to build faster apps faster?
At the end of this workshop, you'll know how to:
- Create Remix Routes
- Style Remix applications
- Load data in Remix loaders
- Mutate data with forms and actions
by

Server-side Auth with Remix, Prisma, and the Web Platform
Node Congress 2022Node Congress 2022
34 min
Server-side Auth with Remix, Prisma, and the Web Platform
In this talk, we'll get a live coded demo of building custom hand-rolled authentication. When you have the right tools (and we do), authentication can be quite simple and secure. This is more (and better) than just: "Install this library and you're good to go." When we're done we'll have our own auth code that can evolve with our ever-changing requirements without a need to learn some library-specific APIs. We'll be leveraging the Web Platform the way it was meant to be done to give us simple and secure server-side authentication for the web.
You can check the slides for Kent's talk 
here
 as well as 
demo code
.


Don't Solve Problems, Eliminate Them
React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.


AHA Programming
React Summit Remote Edition 2020React Summit Remote Edition 2020
32 min
AHA Programming
Are you the kind of programmer who prefers to never see the same code in two places, or do you make liberal use of copy/paste? Many developers swear the Don't Repeat Yourself (DRY) philosophy while others prefer to Write Everything Twice (WET). But which of these produces more maintainable codebases? I've seen both of these approaches lay waste to codebases and I have a new ideology I would like to propose to you: Avoid Hasty Abstractions (AHA). In this keynote, we'll talk about abstraction and how you can improve a codebase applying and creating abstractions more thoughtfully as well as how to get yourself out of a mess of over or under-abstraction.
Transcript
Intro
Hi, everyone. My name is Kent C. Dodds and I am super excited to be talking to you virtually. I hope that you're all healthy and happy and doing well. And I'm excited to be talking with you about AHA Programming. So go ahead and take your DRY and your WET programming principles, set them to the side for a little bit and let's talk about Avoid Hasty Abstractions, AHA Programming.
So I've got some links in here that might be interesting to you, like my slides. And I'm coming to you from Utah. I've got a wife and four kids and a dog and they're awesome. I've got a website on the World Wide Web and, in particular, testing javascript.com. If you haven't tried it already or looked at it, definitely give that a look. It'll teach you everything that I know about testing, which is not a small amount. And EpicReact.dev is going to be even bigger, such a huge amount of content that will be available to you at EpicReact.dev in the very near future. So look forward to that. Take a look at the rest of this stuff later. Let's go ahead and get into this.
Live coded contrived example of the lifecycle of an abstraction
[01:28] So this is what we're going to be covering today. This is a live coded contrived example of the lifecycle of an abstraction. So, hopefully, you can relate to this, even though it's a little bit contrived, but I think that you'll enjoy it nonetheless. And we're going to be considering what's important and why it's important to be thoughtful about an abstraction. And we're, basically, going to be taking this story ... Oh, it's an actual example of a story told Sandi Metz in this blog post around Wrong Abstraction that I strongly advise you take a look at.
We're not going to be going through slides. Most of this is in my text editor here and it's not passively consumable. So you need to decide right now whether you're going to be focusing on Twitter or on my talk, because you won't be able to do both very effectively. So just choose. I'm not offended.
[02:17] So here we are in 02.js and I'm going to be using a tool called Quokka.js. It's an extension for VS code and, among other things, it allows me to console.log in here and it will show in blue what the value of that log statement is. And so that, we're going to be using quite a bit.
So we have an application and we have a user object here. This is Phil and Phil has a name and a username, and in three different places of our application, we've got code for pulling that user's username for the first and the last name. So this is their "Display Name" that we're going to be displaying throughout the UI of our application.
[02:54] Now, you may notice we actually have a bug in here and this is our first part of the abstraction. Here, we're saying "Philip undefined," but Philip's name is Rodriguez, that's his last name. And he is frustrated that it says "Philip undefined" when he logs into our app. And so we've been given the task to fix this problem. And when I was working at a company before, I remember they would say, "Hey, we've got this bug on this page." And so I'd go fix it. And then the QA manual tester over there would say, "Hey, Kent, I thought you said you fixed it." And I said, "Yeah, I did." He said, "Well, it's broken over here." "Oh, shoot. Yeah. I guess that was copy pasted. So let's go fix it over there too." And it was a real pain.
So we build abstractions so that we don't have to fix the same bug in lots of places. And we have three places where we're doing the exact same thing. So rather than fixing the bug right here, how about we just make an abstraction and we fix it in that one place and then all of the other places will get that fixed automatically.
[03:51] So let's go ahead and do that. I'm going to make a function here called "Get Display Name." We'll take a user and then we'll return this and we'll generisize it so we'll take that user, get the name and, instead of the "First and last," we'll do "First and last." So let's go ahead and we'll replace all these with "Get Display Name" for Phil and then we'll fix it in this one place last. Ta-daa, and all of the places were fixed.
We're really happy about this because it means that we don't have to fix it in all of the other places. We just fix it in this one place. And if we ever want to make changes, we can just make changes to this one function, which is awesome.
[04:32] Well, as it happens, we do actually need to make some changes. And that is if the profile page we decide, we want to include the "Honorifics." So let's say Dr. Philip Rodriguez is, "Hey, it would be really cool if my profile page says I'm a doctor. I went to a lot of schools. So I want people to know I'm a doctor."
And so the product manager comes to you and says, "Hey, we want to add the 'Honorific' to the profile page, the display name there." And you say, "Okay, cool." So you come to code and you're, "Oh, yeah, I wrote this abstraction for this." So because the abstraction exists, our natural inclination is to go into the abstraction to enhance the abstraction to support the new use case and also just to see if it already supports the new use case. So we're just naturally inclined to go to the abstraction first and we see this and we see, "Oh, there's no support for 'Honorific' so I could either remove the abstraction here or add that use case to this existing abstraction. And it's just really natural for us to prefer to use the existing abstraction for various reasons. Maybe we think that other people might benefit from this extra use case, or maybe we just feel, since we're already using the abstraction, I don't want to walk away from all of the benefits the abstraction gives me. And in a real world scenario, that could actually be quite a bit. And so you wouldn't necessarily want to just remove the abstraction just for adding one feature.
[06:00] So it seems a lot easier to just enhance the abstraction to support the use case. So that's what we're going to do. And what we'll do is we'll take "Options," but not everybody's going to pass "Options," right? So we're going to default that to an object. And I don't want to just call this "Options." We'll de-structure this and we'll just take and include "Honorofic" and we'll default that to "False." We don't want to break existing users of this abstraction. So we'll say "Include honorific here." We'll grab a "Display Name" and return the "Display Name." So that's just a regular re-factor. We haven't changed anything yet. Now, we'll take that "Display Name," and if there's "Include Honorific," then we'll say the "Display Name" is what it is. We'll put that in a template literal there, but we'll include the "Honorific." So we'll say "User.name.honorific." Great. And then down here in the profile page, we can say "Include Honorific?" "Yes." And boom, we've got it. We're super happy about this. We commit that, we get it reviewed and people are, "Wow, cool." We re-used the abstraction.
Now look at all the power that we've got with this abstraction. Let's go ahead and write a couple of unit tests to make sure that we don't break this feature that we've added. And we move right along and, in the future, somebody comes around and says, "Hey, we need to support a username for the user card. So we want it to say their name and then in parentheses their username. And so you say, "Okay, that should be pretty straightforward." We go to the abstraction again, we see that's not supported. And rather than removing the abstraction from our code, we're going to add this feature to the abstraction, but we don't want to break the existing stuff and so we're going to touch as little as possible. And we'll just add another option here for "Include Username." And we'll default that to "False," because we don't want to break existing users of this abstraction. And we'll say "If include username," ... Except you've got to spell it correctly otherwise it won't work. And we'll say the "Display Name" is the "Display Name" as it is currently and then parentheses and then whatever the username is. So user.username. Great. And then down here we can say "Include username." "True."
[08:14] Perfect. This is exactly what they wanted. We were able to encode that into the abstraction and we add a couple of tests to make sure that this is supported. And actually in the process of adding tests, we realize that there's some combinations of these options that we don't actually support or we don't actually need in our code base, but our abstraction supports. And maybe we realize that maybe we don't, but we know that those use cases are supported where you could provide both of these as "True." And so we add tests for that just to make sure nobody breaks that existing feature so in case anybody might want to use that feature in the future.
And so it's not too complicated. It's a pure function. It's really easy to test. And so we go ahead and add a test for that. And then later on we get another feature request for this code and they say, "Hey, our navigation, we want that first name to not be a first name, but to be a first initial." And so you go back to the abstraction, you say, "Okay, that's not supported today." I don't want to lose the benefits of having the abstraction. It's well tested. And so I'm just going to add my stuff here, but I don't want to break anything that already is there. I don't want to break existing codes. So I'm going to take a first initial. We'll default that to "False," so existing users of this abstraction aren't broken. And we'll take that first initial as an "Option." And we'll say, "If the first initial ..." Then we want the first name to be just the first initial.
[09:40] So what I'm going to do is we'll take this out. We'll just call this "First" and we'll actually assign that to a "Let" here for "First equals username first." And then if the first initial is "True," then we'll say, "First it's actually going to be equal to the First," and we'll slice off the first character and add a dot. Okay, cool. And then we can come down here and say "Include ..." Or actually it's a, "First initial is True," and boom, we've got all of these use cases supported our abstraction. We add a couple more tests in here and we're really happy with this.
And there are two things I want to call out about this: First off, we now have three uses of this abstraction and maybe there are more throughout the code base, but these three don't look anything alike. They have nothing in common with one another other than the fact that some of them show the first and the last name, but each one of them has very distinct differences from the others. And so this is actually pretty common to happen to abstractions is that eventually the abstraction evolves beyond the initial use case and that's not necessarily a bad thing, but all of the use cases have diverged from each other pretty significantly. And so even though our abstraction supports so many things, they actually are supporting use cases that aren't entirely related to one another.
The other problem with this is, as we're writing tests for this, we're going to be writing tests to support use cases that we don't actually have. And while that's maybe not a terrible thing, here's a problem with that. As we write all of these tests to test use cases, when we come in to re-factor this, if we want to make improvements to it, then we have to make sure that our re-factorings support everything that our tests say our abstraction supports.
[11:30] But the only thing that cares about that use case is the test. So it exists for itself, and that is super useless. The test is intended to make sure that the use cases that you need to support are continuously supported. And if the only one who cares about it is not the users, but the tests, then just delete the test and now nobody cares about it.
And so thoughtlessly adding features to this abstraction, we wind up in a really hairy situation and it doesn't stop here. No, we've got some more to do. What if the profile page no longer wants the "Honorific?" So we're, "Okay, that's fine. We can just remove the 'Honorific.'" Boom, it's gone. We're happy, we save this, commit it, push it, it's merged. We're happy about this because all it took was removing that option. And this is what normally happens. And we don't actually think about pulling out the "Honorific" option and getting rid of the code that's specific for the "Honorific." Or maybe we do think about that. And there are a couple other reasons why we might not want to remove it. For one thing, the cost of keeping it in place is pretty low, or it feels low. And the risk of removing it and accidentally breaking something, that actually feels high. And so with that cost versus risk analysis there, we just decide, "Oh, let's just keep it in there. I don't want to break anything." We do this a lot with CSS in particular, like global CSS.
[12:54] I'd much rather add something new than modify something existing or, heaven forbid, delete something existing, because it's so hard to identify if really that's being used. And then there's always the lingering thing in the back of your mind, like maybe someday we'll want to include the "Honorific" in the future. So we'll just leave that feature and then nobody will have to make any changes to support that use case in the future. And that also is problematic because we have Git and we could go back and look at what the code was at that time.
So it is not a costless thing to leave this code in place because we have to maintain it as we make refactorings to it if we leave it in place. And the only one who cares that this code exists is the code and the test itself. So if we remove them, then nobody cares and that's fine.
[13:45] So we're not quite done though. What if our user card here, instead of the first and last name they decide, "Hey, I actually just want to show the last name." Now, doing that with what we have here is actually really easy. We just remove the abstraction and then we just say. "Phil.username." But because the abstraction exists, it just draws us in and we think, "You know what? Instead of "Include username," I'll have an "Only username." And then up here I'll accept that "Only username," We'll default that to "False" so we don't break other people. And I don't want to touch any of this stuff. So I'm just going to add this here to the bottom and say "Only username. Display name equals user.username."
And there we go. We've got support for this new feature and we have now two options that nobody cares about except for the code itself and the tests that were written to make sure we don't break those use cases.
[14:40] So we've wound up with an abstraction that's actually quite a bit more complicated than it needs to be and we can re-factor it, but we've got all these tests now that are making sure that we don't break these use cases that we actually don't care about. And so it's just become a tangled mess. And this is a pretty simple function. It's just concatenating the strings together. Think about your complicated React components or your Angular components or whatever it is that you're writing and all of these different abstractions that you've built around this stuff, and it's pretty easy to build yourself up into an abstraction that's just scary to work with.
How to avoid building scary abstractions
And so how do we avoid this problem? Or how do we back out of this problem when we're in it? And this is something that Sandi Metz talks about in her blog post The Wrong Abstraction. I really advise that you take a look at this because it's really great. And she has a talk here that you can give a watch to. But, in here, what she says is that, "The fastest way forward is back." So the idea is first you reintroduce the duplication inlining and then with each color you use the parameters being passed to determine the subset of the inline code that's specific for the colors, what the color executes, and then delete the bits that aren't needed for that particular color. And so, in this case, that, basically, means we'll make three copies of "Get display name," and inline it into each one of these and then remove the pieces from each one of those that are no longer needed.
[16:07] So let's just walk through that really quick. What I'm going to do is console.log right here. And I just need to have a console.log right here that's the same as this one. And ours is pretty simple. So I don't really need to make a separate function. I'll just look at the function and grab the pieces that I need. So here we just need the first initial and then the last name. So that's, pretty much, all this code that I need for this. So what I'll do is I'll grab this right here. We'll put it right there and we're going to get the first from "Phil.name.first." Okay. So that's getting our p-dot and then the rest of this is right here. So let's grab that. And instead of "User" that's going to be "Phil."
Okay, those two things are the same. So we can grab this now and put it in place of the abstraction. Now, this situation, or this navigation file, is no longer using the abstraction. And we could come in here and delete the stuff that's not being used anymore, but let's keep going and inline the abstraction into all the places where it's used and then we can remove it.
[17:11] So the next one is just the first and the last name. And so that is right here ... Or, no, it is this part right here. So let's just grab that. We'll add a console.log right here. And the first is going to come from a "Phil.name.first," and this is going to be "Phil.name.last." And we're going to need to put that in a template literal there. There we go. Cool. And that's exactly what we need. So we'll just replace those. Get rid of that. And now we've removed the abstraction from that one. And then for our last one, it's just the username, and all that we're using from the abstraction for this is just user.dot.username. So we'll come down here and that's so easy. I'm just going to say, "Phil.username." There it is. We have the exact same thing that we had before. And, as it turns out, we can remove this whole abstraction. It's gone from our code base. That really big, hairy, scary thing that you were worried about is gone. And maybe you have it just all inlined like this. Or maybe that was a big component and you have four different copies of the same component that are just slightly different for each use case.
Now that you have those four different copies, you can see the similarities between some of them and maybe there are two different categories of that same abstract and there's the one that shows the dropdown and then there's the category that doesn't. And so we'll just keep those as separate things, whatever the case may be. But, because you've done this, you're able to identify the commonalities between the different abstractions and the differences. And in your current state in building this today, you're a lot more able to create an abstraction that works for what we have today. And because you've experienced ... You have some battle scars on bad abstractions, you're more thoughtful about the abstraction that you're making.
Conclusion
[19:02] So with all of this, I just want to wrap up with a couple of takeaways: First off, Do not Repeat Yourself, or DRY, that's not necessarily a bad thing. Do not Repeat Yourself in theory is a good idea because it does allow us to get rid of some business logic bugs in one place, or just even some typos if you're not using TypeScript, but it can really help you avoid some duplication. Duplication is not inherently bad, but it can be a problem and it can just propagate a bunch of bugs all over the place. So Do not Repeat Yourself itself is not necessarily bad.
But the key here is that you can't tell the future. So the only thing you should really be optimizing for is change. So one thing that Sandi Metz talks about is, "Duplication is far cheaper than the wrong abstraction." So preferred duplication over the wrong abstraction. I agree with that wholeheartedly and I think that, as you duplicate things and just wait for commonalities in that duplicate code to scream at you for abstraction, then those abstractions become so much more obvious for you and you can build out the right abstraction for the use cases that you have present for you at the time.
[20:15] So as you're building out stuff and you have all these ideas like, "Oh, cool abstraction here. Cool abstraction there," just keep duplicating stuff, copy, paste, move it around, and then once you're all done, you can see what you have and you see the commonalities and be, "Oh, actually these two things are not as common as I thought they were when I first wanted to abstract them. So I'm glad I didn't. We'll just leave them as separate things." Or, "These two things are really common. There's just three things that I could parameterize," and then you can make an abstraction for it.
If you have shared code with lots of branches, then I recommend to you to resist the urge to add more conditionals to it and instead re-factor it first. And go and learn everything that you can about the users of that abstraction. And maybe there's something that you can learn about the abstraction as a whole so that you can maybe split the abstraction up into multiple pieces that will be easier to manage themselves.
[21:11] So I've got a couple resources for you: Sandi Metz gave a talk that is really good around this same idea called All the Little Things. Definitely give that a look. And then the blog post, of course, is also great. And then I have a blog post about this concept, AHA Programming, you can and check out on my blog and I have a testing variant of that, as well. And yeah, follow me on Twitter because I tweet things. Thank you very much. I hope you have a wonderful time at the conference. Stay happy, stay healthy and subscribe. Thank you.
Questions
[21:45] Jason Lengstorf: All right. That was excellent. Kent, as always, that is a wonderful talk. If you are new to the AHA Programming concept, I think it's such a cool thing. I always love seeing what Kent does. And so now let's bring Kent back to the stage and we will do some Q
&
A. We've got some great questions in the Slack. Kent, welcome back.
[22:09] Kent C. Dodds: Thank you. Thank you. I'm so excited to be here and I always enjoy spending time with you, Jason, and our 4,000 friends or however many people are watching right now.
[22:20] Jason Lengstorf: Yeah, I think we're up above 4,000 right now on the live stream. So, holy crap. So I had a question because actually I've been following you for a long time and I remember the origin of AHA and so I'm going to put you on the spot a little bit. But AHA wasn't always called AHA. So can you talk a little bit about the origins and how you got to now?
[22:44] Kent C. Dodds: Yeah. So AHA was my frustrations with DRY programming as a practitioner early on and I learned about Do not Repeat Yourself and how important it is that you create abstractions for things. And then I found out what ... I think most people find out with that is eventually the abstractions you create are really bad. And then I heard about WET programming, which is Write Everything Twice. And I was frustrated that, as well, because then you have to fix bugs in multiple places. And so I just thought they were both way too dogmatic. And so I decided let's just be more mindful of the abstractions we make and then everything will be better, hopefully. And so in the process of writing a blog post about this, because I have to write a blog post about everything that I think of, I decided, "Okay. Well, it's not DRY. It's not WET. What's not those things? I guess, it's moist." And so that's what I called it at first, was Moist. And I don't really like the sound of that word and I know a lot of people see it really cringy, but I was, "Hey, it's okay." And I couldn't really think of what that could stand for. So I didn't even make what that acronym is. And I tweeted about it and I got so many people, "That is so gross," or just laughing hysterically about it. So I was, "Okay, okay. I need to come up with a different name." And Cher Scarlett gave me a perfect name, and AHA, Avoid Hasty Abstractions. It was perfect. And it's light bulb moment. I love it for every ... It's just the perfect acronym. So that's where that came from.
[24:30] Jason Lengstorf: Ah, that's great. You briefly mentioned this, but I want to talk ... Well, actually, you know what? You answered it. I'm not going to talk. You talked about the difference between DRY and AHA. So let's go to the Slack and someone asks ... There's a great question here: "How do you implement this project-wise? If you were going to roll this out into a given project, how do you work that into your process?"
[22:54] Kent C. Dodds: Oh, that's such a great question. I think that it's so tempting when we're ... If you're starting a brand new project or you're coming into a project and you're, "Wow, look at the mess of abstractions that we've got here," or whatever, it's just so tempting for you to instantly want to architect the entire thing from the very beginning. And that is an enormous mistake to make. You automatically ... You have a code base of 3000 lines of codes so far and you are architecting it for a three million line code base. You're going to wind up in bad abstractions and you'll never make it to that three million line code base. So it's not one that you want to work in.So I recommend just taking a really iterative approach. Don't worry about duplication. And if you come into a code base and it's got bad abstractions, then what I talk about in the talk and referencing Sandi Metz there, inline those abstractions, and then you can just pretend that it's always been this way, and you're, "Oh, wow, there's an abstraction just sitting here for me," but it'll be totally different from the bad one that you inlined before. So, at least, hopefully, it will be. But that's what I'd recommend, is just be really thoughtful about the whole process. Don't try to architect your whole application for something that it's not today.
[26:14] Jason Lengstorf: So a question here that is, I think, ... "In the context of an abstraction, do you feel abstraction should not be extended? Or would it be better to just extend it and see what happens until you end up with three to four functions and then change?"
[26:32] Kent C. Dodds: So maybe I'm not totally understanding the question, but my thought process normally, and this is something that I really had to fight for, but as I'm working on some code, before I've committed anything, I'm just toying around with stuff, I am constantly thinking, "Oh, this looks a lot like this and so let's just put that in a function." And I really had to fight myself and say, "No, no, no, no, no. Don't do that yet. Just copy it." Even if it's five lines of code, it seemed so duplicate, just copy, paste that because eventually you'll find out one of two things: You'll either find out that you didn't need it at all in the first place. And so taking the time to make the abstraction, create the variable names and genericizing that function was a waste of time anyway. Or you find out that they weren't as similar as you thought they were. So I don't know if that answers the question because maybe I misunderstood it, but that's just-
[27:27] Jason Lengstorf: Well, I'd like to follow up on that actually. So when you say that you realize that they're not as similar as you thought they were, do you have an example? Because I feel that's one of those things that it's easy to say in the abstract and hard to put into concrete terms. So if somebody's thinking about this, when's the case when the same code that you've copy pasted isn't as similar as we think it is?
[27:52] Kent C. Dodds: Yeah. That's a great question. So an example of this that I just experienced recently, and especially it's a React conference, so a React example, I had a "Login" and a "Register" button, very similar, just different words or different Reo labels for the modal, they pop up, different colors and stuff. And I thought, "These are really similar. I could make a React component, just take a couple of props. But I've held off, and I found that if I were to make a component for this, there would be so many little props that are this is what the Reo label should be. This is what the title of the modal should be. This is what the type of button it should be. And I just don't see that type of an abstraction being any simpler than the duplication that I have instead. Each one is six or seven lines of code. Now, there is a little piece in there that the modal that it pops up has a little "Close" button that is styled specifically for the "Login" and "Register" modals. And so all I did for that was I just extracted the CSS for it because there's no variables or anything ... Or not the CSS, but the JSX for it. So I just created a JSX element and then I inlined that element as a variable. And so I'm able to take that little piece of commonality without making it a whole function component that has 12 props on it.
[29:17] Jason Lengstorf: That's a really interesting distinction too, because in both cases you're talking about code that would visually look the same, what shows up in the browser, it visually looks the same. It's a "Close" button or it's a registration form, but the implementation is where the difference starts to come in. If you have to change every part of those attributes, you're not really writing an abstraction, you're just giving yourself chores.
Kent C. Dodds: Yes, yeah. Exactly.
Jason Lengstorf: Yeah, that's-
[29:42] Kent C. Dodds: Anytime you want to make anything that makes them slightly different you have to add another argument, another prop and it's just more homework for you. And, at the end of the day, what you end up with is either copy pasted JSX that's just two copies of almost the same thing. Or-
Jason Lengstorf: Right.
Kent C. Dodds: ... a function component that you're calling ... That is almost the same amount of lines of props. So what are you buying yourself there? Not much. Just chores.
[30:10] Jason Lengstorf: Totally. Totally. Okay. So another question, just following that, "Is the cost of a bad abstraction usually much worse than that of duplicating the code in tests and possibly duplicating bugs?" What's your experience with that then?
[30:27] Kent C. Dodds: That's a great question. And it's pretty nuanced because like, I don't want anybody coming away from my talks saying, "Oh, Kent likes duplication. He hates abstraction." That's absolutely not the case. As a library author, clearly, I make many libraries and I see the value of abstraction. I just see there comes a point where the duplication becomes a real problem. For this "Login" "Register" example that we just shared, that duplication, it's right there, and if there's a bug in one, it's really easy to just fix the bug in the other. Not too much of a problem. But if you find yourself duplicating over many, many files, then maybe there's a good case for an abstraction there. So I can't give you a rule because there is really no rule about this. It's all just nuanced and ... Sorry. That's not very helpful, but hopefully, the talk was.
[31:23] Jason Lengstorf: No, I think that's great. And with that, we are going to start moving on. That's all the time we've got. Kent, thank you so much. It's always a pleasure and we'll see you-
Kent C. Dodds: Thank you.
Jason Lengstorf: ... in the Slack.
Kent C. Dodds: All right. See you.


Kent C. Dodds: Consume, build, and teach — and level up your career
14 min
Kent C. Dodds: Consume, build, and teach — and level up your career
Article
Even though his bio offers quite a hefty reading, he only applied for one job in his career. The rest came along as he was building his name as a renowned speaker, teacher, and a prolific figure of the open-source community. How did Kent do it? “Commit to creating high-quality content,” he says.
What led you to programming?
I had a friend when I was a teenager who was really into it, and he tried to teach me. But I just couldn't get it — it didn't make any sense to me. So I never really thought I'd get into programming, but I liked computers a lot, and I ended up going to school for electrical engineering. 
Well, that didn't work because I'm not good at math. But right when I started the program, I got a job at a company uploading videos to YouTube and that sort of thing. The work was tedious, so I decided to write a computer program to automate lots of the work I was doing with the knowledge I had about programming. And that was the first spark of things for me to use programming to solve real-world problems. 
What is the most impactful thing you ever did to boost your career? 
Committing to creating high-quality content. That might sound obvious because I'm a full-time educator now, but I would not have gotten my job at PayPal if I hadn't been so active with my blog. In fact, lots of my jobs came out of me being involved in the community around meetups, conferences, or open-source projects. 
How do you choose topics for the content you create, be it for your blog or podcast?
I don't think too much about the content other people are creating. And I don't often consume it. My ideas come from the things that I'm working on, things that I'm learning myself, or — when I was working with a team of developers — the things that I had to remind people of in code reviews regularly. Anytime that I would have a code review comment that was pretty long to describe my position, that was an excellent opportunity for a blog post. Also, if people ask me about a topic regularly, I'll make a blog post rather than answer that question multiple times.
What would be your three tips for engineers to level up their career? 
The number one thing I tell people is to be a nice person. I know that sounds fluffy or silly, but it cannot be overstated. You will get so much further in your career and just in life in general if you're a nice person. That doesn't mean that you take people being jerks lying down, but how you interact with others is out of kindness. You could be the best engineer in the entire world, but if you're not a nice person, you will not reach your full potential or accomplish your goals, whatever they may be.
Second, it's just as important to decide what you are not going to learn as it is to decide what you are going to learn. You could jump into countless things — and there are successful people who are polyglot programmers, but I can't speak to that a whole lot. All I can tell you is that in my experience, focusing on specific things that I want to be truly good at has worked out great for my career. That doesn't mean that I closed myself off to other things. With my
website rewrite
, I have been doing a lot of dev ops-related work and a lot of back-end stuff that I've typically not been involved in. You want to keep your head up on what's going on outside of what you're doing so that you know what direction to go in when you come across problems you need to solve. However, finding a focus on what you want to be good at has helped me a lot. That way, you feel a little less stressed.
And the third one? 
Learn how to learn effectively. It's a three-step process: you consume, build, and teach. The consumption of newsletters and Twitter and whatever inspires you, but you don't want to spend too much time doing that — implementing it into actually building something matters. This happens naturally if you work at a company, but maybe you're not making the things you want to learn, so you may want to start a side project. The building phase is where you get experience, but you also want to solidify that experience. How? You start teaching. You don't necessarily have to teach it to people, it could be stuffed animals. The goal of the teaching is to retain in your mind what you've learned through the building process.
What are you working on right now? 
The big thing I'm working on right now is a rewrite of my website. It'll be much more than just a developer portfolio — I'll have user accounts, and there'll be fun things that you can do with it. And because it's more than just a website, I'm using
Remix
, a new cool framework in the React ecosystem. I'm also working on updating my material on
TestingJavaScript.com
and a TypeScript course as well. 
So, whatever I'm working on, it ends up resulting in lots of opportunities for content.
Do you have some rituals that keep you focused and goal-oriented? 
I have a notepad where I keep all of my notes of what I'm going to do for the day so that when I'm checking things off, I'm not distracted notifications. I've tried apps for that, and that does not work well for me. 
I also am a firm believer in inbox zero. I have my work inbox and my personal inbox, and I keep them both at zero. And I kind of use that as a to-do list. 
And if I'm not feeling excited about working for some reason, I will often hop on my Onewheel, which is an electric skateboard that only has one giant wheel in the middle. It's just a total blast, and I'll hop on that with my backpack and a charger, and I'll go to a Starbucks or a park just to declutter my mind.
What things in the React universe are you excited about right now?
React version 18 is coming out soon. The experimental version is out there, and it's fun to play with. I'm just really thrilled that it's no longer a concurrent mode but concurrent features that you can opt into. Cool things like that will enable React server components in the future. 
But the biggest thing I'm excited about is Remix. That's huge. It eliminates a lot of problems that are solved well other tools, but when I'm using Remix, I don't have those problems, so I don't need those clusters.
You already said that teaching is an integral part of the learning process, and you stand your word since you're also a full-time educator. What inspired you to enter this field?
I have been a teacher for as long as I can remember. I grew up in a church where you talk in front of your peers from a very young age, and my mom was an elementary school teacher, so teaching has just always been a part of me. 
I really just enjoy sharing what I'm learning with others. As far as teaching technical topics, I gave my first workshop when I was still a student at Brigham Young University. With my fellow, we taught how to use AngularJS, and I got Firebase to sponsor pizza so they would show up, and that was pretty fun.
Then I started teaching on the side at
egghead.io
right after I'd graduated. That was when I first got a paycheck for teaching. And I realized that teaching could be quite lucrative and support my family and me as a full-time endeavor. So I did it — I quit my job. I'm a very risk-averse person, so I'd done teaching as a side hustle for four years just to verify that I could make this work.
When TestingJavaScript was released, and I got that paycheck, I realized that I didn't need my PayPal salary anymore. I could just focus my daytime on teaching and give my evenings back to my family, which was a nice trait.
Apart from that, how has teaching impacted your career? 
Earlier I mentioned that pretty much all of my jobs came because I was perceived as an expert. After the first job, where I was an intern and then converted into full-time, I never applied to another. I worked for four different companies, and they wouldn't have recruited me if they didn't know who I was and what I was doing. My content is how they knew who I was — I just made it easy for them to find me. Teaching made that impact. It made my career. 
We talked about React and Remix. Are there any other open-source projects that you'd recommend keeping an eye on or contributing to?
I have some myself. React Testing Library is probably the biggest one that people are familiar with. And if React isn't your jam, then other framework versions of the testing library. 
React Query is also really popular. If you're using Remix, you don't need it, but if you're not, I strongly advise using React Query cause it's a stellar, fantastic library, and Tanner Linsley, the creator, is a stellar and fantastic person. 
What pieces of your work are you most proud of? 
Probably the biggest thing I've ever done is
EpicReact.Dev
. It has helped tens of thousands of people get really good at React, improve their careers and make the world a better place with the skills that they develop. My whole mission is to make the world a better place through quality software, and I feel like I've done that best with Epic React. 
There are things that I've built at other companies that are still in use, and I'm proud of those cause they've stood the test of time, at least these last few years. But of everything, I think Epic React has made the biggest impact.
***
Follow Kent on Twitter
 and listen to his favorite 
Spotify playlist


Panel Discussion: Testing
React Summit 2020React Summit 2020
21 min
Panel Discussion: Testing
Video
♪ I would like to welcome Tomasz Lakomi, Kenzi Dotz, Iris Schaffer and Sophie Au to our panel. Are they all here? Hello? Hello. Ah, excellent. So good to see you all. Hi. How are you all doing? Yeah, not too bad, not too bad. Awesome. Sweet. That's fantastic. So I feel like a little bit, coming back to the among us thing that was brought up earlier, I feel like a little bit of the imposter in here, because I do write tests in the projects that I control, but I also worked in many different agencies and companies and projects where testing was met with skepticism, let's put it that way. So I'm really excited to hear your opinions and ideas on this topic, because I think I was not the only one struggling with this like inner tension of kind of knowing that tests provide a big value, but then also seeing like bad practices and seeing problems. So would you all very quickly introduce yourselves and what you think is like the number one value from testing? Let's start with Iris. OK, I'll start then. So my name is Iris. I work at Spotify in Stockholm in Sweden. And I think for me, the number one benefit would be the quality for the end user, just ensuring that on every release without having to manually test every time, every feature. Oh, yeah. Been there, done that, got a T-shirt. What's your take on this, Sophie? Hey, everyone. I'm Sophie. I'm a full stack front end T developer at Donut in Berlin. And for me, like I think the main thing about testing, similar to Iris, is like knowing that the stuff I'm actually pushing to production works. And like, especially because we do mobile, we do a mobile app. So it's not like you can just push a quick fix, but you actually like have to do a new release. So actually kind of being confident in that the app we're shipping to the user works and we don't have to push like 20 buck releases quick after. That's really good. Oh, that sounds convincing. Tomasz, how about you? Hey, everyone. So my name is Tomasz Rokome. I'm a senior front end engineer at Odex Group. And I also record videos for Echel.io. And when it comes to kind of the number one value of testing, apart from the things mentioned by both Iris and Sophie, I would like to say that testing makes me sleep better at night. As in because I push something to production, I don't have to worry for the entire evening that it is going to break. In fact, we've pushed something to production an hour ago and I am not checking Slack or notifications right now. I know that feeling and I know the other side of this. Kent, how about you? I learned a bunch from your testing talks and workshops. Thank you. Yeah. So my name is Kent and I made testing javascript.com where I teach people everything that I know about testing. And I don't have a whole lot to add to what's been said. I'll just one thing is I got started with testing with my open source libraries because every time I pushed or I wanted to push a release, I had to go through this. I brought up the library on a page and clicked around all over the place. It just took a lot of time for something I was doing for free. So I thought, I wonder if I could just clone myself and make, you know, do that with my clone so I can go on and move on. And that's what tests are for me. It's like a thousand little kents going through all of these different things I always did. I see. Interesting. So I heard a bunch of really good reasons for why I would want to test. But I know, bear with me, this has been a few years ago when I started, actually not a few years ago, that has been a long time ago. But when I started with software testing, I basically had to read a really thick book and it was not very fun. But how do I, if I am a React developer who's just starting, how do I get started with writing tests? What's a good path? Well, I'll go ahead and get started there. So I think that something that's important to keep in mind with testing is that testing is not anything different from regular software development. So it's just another thing that you're writing software for. And so having an idea of what a fundamental test even is, is really useful. And basically a test is software that will give you some sort of notification when things are not working as expected. And so, yeah, like how do you get started? It really, the answer to that question is the same generally as like how do I learn FrameworkX or how do I build this feature or whatever? Because it's no different from any other software that you're going to write. Right. But I've seen lots of software out there, sorry, courses or literature that basically assumes you're starting on a greenfield project. But I think for most people, that's not the case. Most people here watching right now probably have a huge code base and wonder like how do I even get started? Even if I know how to write tests, which a lot of the material out there covers, how do I know how to start in my existing code base? How do I get the biggest bang for my buck? How do I find out? Where do I start? I'm happy to take that one. So in my experience, like I'll assume it's like React, like web app. End to end tests are usually kind of my first go to, which essentially, generally, even if you don't actually write tests yet, you have someone who's checking that the app works right. I mean, worst case, it's the user when it's in production. But you have someone that's going to tell you, hey, the checkout button is broken. And just writing end to end tests essentially kind of automates that check. So my general recommendation is kind of what's the most crucial part of your app? Is it your checkout button? Is it, I don't know, like you're sending some financial data around just write a single end to end test for the most important functionality of your app. And then from there, kind of branch out and try to cover it kind of as much as possible. And don't get too bogged down in like unit tests and like the 5000 edge cases. Just make sure you have like a rough idea that covers like 80% of the functionality. Right. That sounds good to me. And I know that I wanted to do that so many times when things broke in production and I was working with customer projects. And then you would get calls to unholy hours to your project manager who then like tries to call you while you're trying to sleep. How can I convince? So now that I might be the person who's like, OK, I see the problem. I want to write tests. I learned how to write tests. And I now know where to start. How do I convince my team to A, join the effort and B also how do I convince my manager that I'm not like slacking off and not spending time on something that's useful? I can take this one because I actually have a blog post in around the same idea. So there's a couple of things around here. First up, you shouldn't have to convince your manager, your product manager or anyone really. Because the same way I don't have to convince my manager that I would like to use your state or use effect or any other hook from React. Like I consider testing to be a part of the thing that I'm trying to deliver. In other words, I as a software engineer, I am getting paid to not only build and ship software, but also ship software that actually works and brings value to our users. Ideally, I would love to get paid for shipping broken software, but that's not how the world works. But in a more realistic scenario in which you have a legacy code base and nobody's writing any tests and you would like to create this test setup and to kind of pave the way for future generations who are going to join this project. I would like to start honestly by convincing our managers or product managers or anyone how much time do we waste resolving production issues. And how many of those production issues could have been avoided if we simply had an end-to-end test or other tests, unit tests and so on. Because for instance, consider a website like Twitter. If on Twitter, the login page is broken, you literally cannot do anything. Because if you are locked out of Twitter, you can of course read the tweets, but you cannot tweet, you cannot add anything to the platform. And with only this one test in place, you are able to ensure that, okay, by the way, we are absolutely convinced that the huge part of our website is at least accessible to our users. So start with not the fact that I want to write tests, but talk instead about I want to ensure the quality of our software. Because people are scared of the word test, but they tend to like the word quality a bit more. But what if then your manager asks, so why are you writing broken code in the first place? Right? I know the answer to that is that's something that I have been asked. Sure. I would say that I don't write broken code. My colleagues, they also don't write broken code. But all of us combined tend to produce something that can be broken. So I would like to say that everybody tries to do their best, but sometimes things just happen. And it's not anybody's fault that something is going to break in production. And by us having the best process in place that we can, we can ensure the utmost quality of our software in production. I think that's a good point. Having a process is key and is something that managers also usually do understand. Because you usually have a process already, at least for project management purposes or product planning. There should also be a quality assurance process, I guess. Also, another interesting question that does come up is when we do start to write tests, especially on a legacy code base, but the legacy code base also still is alive and still is evolving, then sometimes you end up with situations where the website is perfectly fine. It's just the tests are failing. How do you deal with that? Is there any patterns that you can spot in test code that you want to probably avoid to not end up in situations where you create tests that sometimes fail, sometimes pass with no changes in the code made, or there's small changes in the code, but not really in the functionality, but still the tests don't pass anymore? Is there any anti-patterns that I should be looking for in my tests? I think I can take this one. I would say if you have tests that keep failing over and over and over again, you're probably testing something that is internal to the component that you're testing. Rather than testing how other components communicate with you, you're testing something internal. Maybe you're testing that this function is being called, but then you change which function is being called, your test breaks, and then really what you should be testing is, is this displayed to the user or is this API being called? It shouldn't be the detail of how you implement it. It should be the end result that you should be testing. Right. Okay, cool. And you said that a valid point to start are E2E tests, but that raises the question, what do you use for E2E tests, for end-to-end testing of web applications? I don't know about everyone, I know Tomasz's opinion on this, but I'm a huge fan of Cypress. I've been using Cypress for a very long time, and it's fantastic. It has such a great developer experience. That's the biggest reason that I use it. There's Puppeteer, there's Test Café, there's Selenium, and there's various others. But of all the end-to-end testing software that I've used, Cypress is by far in a way that has the best developer experience. And that's what you really need out of a testing tool is, anything can throw an error when there's a problem, but not every testing tool is capable of helping you identify what's causing the problem, which is really critical when a test is failing. That's fair. And an interesting question follow-up on this one. End-to-end testing on browsers, I kind of know what to do, but what if I have a mobile app? So yeah, if you have a React Native app, the one tool that we're using is Detox. It works somewhat similar to Cypress. It is super annoying to set up, I have to admit. I think it took us two days, so the DX isn't great. But once you get it working, it actually does its job quite well. Yeah, it's a bit of a different experience just because you don't have a browser, but it's running in the simulator. But if I remember correctly, I haven't actually written into SSS in a while, but syntax-wise, it's very similar to Cypress as well. I see. Cool, cool. And with the testing tool conversation comes something else, because Kent, you mentioned a bunch of tools already. And I have at least the feeling that similar to JavaScript frameworks a couple of years back, where they popped up like mushrooms in autumn in a Zurich forest, which there are many if you haven't been, I think testing tools evolve quite quickly as well. And there's at least a bazillion, bajillion different test runners, and every couple of years, our opinion changes on what's the best of them. And I feel the same way. A couple of years back, we had Selenium, and everyone was happy, and then everyone hated it, and then everyone jumped to – I can't even remember what the bits and pieces in between were called, but now we're in Cypress. Once you are committed to a solution, should you stick to it, or should you pretty much continue to evaluate and jump on the bandwagon? What's your opinion and experience? I can take this one. So when it comes to testing solutions, in my humble opinion, the landscape is a bit settled, at least for me, because I'm using Jest, I'm using React Testing Library written by Kent, and I'm also using Cypress. So I am quite convinced that this stack is going to take me to great success in the software that I'm building. But when it comes to chasing this bandwagon, and I know when the next better version of something for end-to-end testing is going to be released, for instance, I am not entirely sure whether you should jump on the bandwagon right away. I tend to think of software in the way that if something is solving your problems, and you don't get any issues because of the fact that you are using a certain library, I don't think you should necessarily have to jump to a better testing solution. Although, I don't know, in the next testing solution, it will be twice as fast, or the test will be written by an AI. I would be definitely interested. Fair, I think. Yeah, I think that's a good... The fewer tests that I have to write to be confident in my software, the better. Exactly. I don't write tests because I enjoy writing tests. I write tests because I like to be able to ship software and be confident that it's working. So if I don't have to do that, if I don't have to write the test, then I'm totally fine using some AI that does that for me. Yeah, same goes for Angular code, for the record. Yeah, that's true. I think everyone agrees on that. Speaking of less tests or fewer tests, if I have unit and integration tests as well as end-to-end tests, can I just scrap these asks, Elunade, from the chat? Can I just stick with end-to-end tests? Because they are the closest to what the customer actually gets to interact with, right? I'm happy to take that one. In my experience, your end-to-end test is never going to check all edge cases, especially when it comes to interactions between components. If your end-to-end test does catch all edge cases, that's A, very impressive, and B, the suit is probably going to run for hours because it's really hard to figure out all the different combinations of component interactions. Don't scrap the tests, especially if they pass and then do their job, then leave them in. But when it comes to writing new tests, my general thing is I go for more an integration-y kind of test than actual unit tests, because you very rarely just have one component on your screen, right? It's always about components interacting with each other. So I think KenTest is a really pretty testing trophy, which is mostly end-to-end tests and then integration tests and all the stuff that is super weird tests. That's when you do unit tests. Generally, I'm also a very lazy person, so if I can cover all the edge cases with integration tests, why would I write unit tests, right? That's just more code I have to write and more stuff I have to maintain later on. That's fair. But I think the speed aspect is what's important. Sorry. Sorry. Go ahead. Flakiness as well, I think. End-to-end tests do tend to be a little bit flaky sometimes because there are so many different systems at play, right? So going a level lower already helps a lot with that because all of a sudden you're only testing your part of the application rather than also the interaction with seven different backend services. So that can help. And then I actually love unit tests as well, but I use them not as much for React components, but more for, say, all of my different functions that do stuff, like all the library stuff that is just somewhere tucked away, right? For that, unit tests are perfectly suited. All right. Sweet. Ladies and gentlemen, thank you so much for being here. You filled my brain with lots of inputs, and I hope that the audience enjoys this as well, and we try to cover as much ground as possible within 20 minutes. Unfortunately, our slot is coming to an end. Thanks again for being here. Thanks again for taking these questions and discussing this with me, and I hope that you are having a fantastic time, and stay safe and stay healthy, please. Thank you. Awesome. Cheers. Have a great day. Bye.
Consume ➡️ Build ➡️ Teach
React Summit 2020React Summit 2020
29 min
Consume ➡️ Build ➡️ Teach
How do you level up? How do you jumpstart your learning when getting into something new? Nobody has more than 24 hours a day, so how do you maximize the impact of your limited time?
In this keynote, I'm going to tell you a bit of my own story, and some tips and tricks that I've learned so you can be as productive as you can be at learning new things and solidifying that knowledge so it's there when you need it.


Panel Discussion: Future of Web Testing
TestJS Summit - January, 2021TestJS Summit - January, 2021
33 min
Panel Discussion: Future of Web Testing
Video
Hey, hey, hey, I'm really happy to be here. I'm thrilled. I'm super excited to kick off this panel about the future of web testing. And I'm so excited because of two reasons. One, a lot of things, great things happening now in this field. Just to give you an example, I checked today in GitHub, and there are already 17,000 repos dealing only with testing in JavaScript. 4,000 of them were written in the last year. So, so many things and innovation happening now in testing. The second reason is because I probably have the ideal panel to discuss all of these trends, really some of the most influential. The people who are building this innovative tool here with me. So how about we start with a quick intro? Let's start with you, Nancy. Would you like to introduce yourself? Sure, I'm really excited to be here. My name is Nancy and I am a solutions architect working at a company called Rango.io. We're a tech consulting agency. So, I've worked with a lot of clients in the past, enterprise and startups, oftentimes with their testing strategy. Cool, great to have you Nancy. Kent, C-Dodd, I'm not sure we even need to introduce Kent, but we will. Kent, please tell us about yourself. Yeah, sure, thanks. I'm super happy to be here. I love the conferences put off by Git Nation. They do a great job. So yeah, I created testingjavascript.com where I can teach you everything that I know about testing. It's awesome, so take a look at that. And actually there's a discount coupon just for TestJS Summit. So I'll share that in the Discord. And I also created Testing Library, which is kind of a funny name for a library. But it helps you test DOM related stuff. So anything that has to do with the DOM, anywhere you can find the DOM. And actually there are other implementations for React Native and stuff like that too. But it just gives you utilities that you need to test UI. That's the main idea behind that. So that's what I do. Cool, and we're about to discuss, of course, Testing Library very soon. Oren, good morning, San Francisco. Hi everyone. Pleasure to be here, super excited to be here with everyone. My background is mostly building products for developers in the last 22 years. I'm guessing that the standard you know is the Aplitur is the visual validations. I was one of the founding members, weeks an early developer. And now the founder of the last six years, founder of Testing. I will focus on AI helping test automation. That's great, and we're also going to discuss testing. Jason, hi. Everyone, I'm happy to be here. I'm Jason Palmer. I work at Spotify for the last almost ten years as an engineer and now a PM. I'm also a core contributor to Jest, and I created JestJUnit. So if you're running Jest in a CI environment, there's a pretty good chance you're using that. Amazing, great, so we're about to discuss now a bunch of topic, a bunch of hot trends in testing, and each of the panelists is going to share his thoughts and experience about each of these hot trends. So how about we start with the CI world? And there is a new giant player, GitHub, now playing in the CI world in the past two years. And funnily enough, I just checked today, and each of the big vendors who operate there for years have approximately 100 extensions or actions, some call these orbs. GitHub in two years already have 7,000 GitHub actions. So it's growing crazily. And my question to you, let's start with you, Kent. Is this just another big giant eating the market, or are they doing things differently? Do they provide new capabilities, opportunities for us developers? You know, years ago, I did a survey, not like a survey, but I took a survey of all the CI services that I thought would be good for the company that I was working with at the time. And I tried a ton of them, and I ended up with SnapCI, which is no longer a thing, which is kind of sad. There's GoCD now as their thing, but, and that's what I used for my company. But then for open source, I was all in on TravisCI, and it served me really, really well for years. But I don't want to get into this too much, but Travis kind of changed the way that they do things in a way that made it very difficult for open source. And so I've been totally moving everything over to GitHub actions. I've been kind of thinking about it anyway. And my goodness, it's such a nice experience. So there's a reason that I think so many people are going over to GitHub for managing their GitHub actions. There can be some concern with the monopolistic approach, I guess. But I don't know, like, I'm just trying to ship stuff, and GitHub actions makes it really easy to do that. So that's, I like it. Can you share one example of any delightful experience, something that just helped you specifically to ship? Yeah, well, you mentioned the 7,000 different GitHub custom actions that you can use. I didn't have to build any custom or, yeah, custom action of any kind. It was just like putting together all these different ones to make things come together in a really nice way. It was just very, I wouldn't say that it was super straightforward. There are definitely some nuances and intricacies and things like that. But once you have it set up, it's actually pretty understandable what you have. And I think that, yeah, just the sheer amount of actions that you have at your disposal is super, super helpful. Yeah. Yeah. And Nancy, I'm curious to hear your thoughts on this matter. Yeah, I think it's actually super cool. I really like the approach kind of GitHub went with. Instead of just focusing on being another CI tool and just focusing on their infrastructure, they really took like that open source approach, really encouraging and fostering the community to contribute and focusing on that marketplace aspect, rather than it being sort of an afterthought. And I think that's where it's really powerful. And that's probably why we've seen so much growth there so quickly. And really now sort of GitHub is not limited by how many developers are putting on to really build out their CI or really understanding the user's need because it comes organically, right? They're allowing the community to kind of dictate where this goes. And I think that's super exciting to see. I think it's hard to predict where it will go in the future, especially, you know, a lot of the clients I've worked with in the past, like moving, switching over to a whole new infrastructure is just a huge undertaking and oftentimes not the top priority and just not worth the effort right off the bat. Yeah, interesting. Both of you mentioned that the marketplace is the thing, like upfront, they build it for you. And beyond, they build it for the marketplace. And this is the core and not some extension like it was in previous CI vendors. Yeah, yeah, sensible. And Oren and Jason, feel free to jump in whenever and everyone, we are spontaneous here. So one thing I really like about GitHub Actions, I guess, is that it's kind of one of the CI providers that's taking the like a Docker-based approach, which is really nice. And it's kind of a new wave that I've seen, I guess, in the last few years. It definitely makes it easier for folks to be able to like reproduce CI steps locally and kind of craft like a decent, you know, CI environment locally and make sure that it works. And then you kind of, you know, it's a lot less, you know, toil, basically, than you might have with other CI environments. Yeah, yeah. So bottom line, I think anyone should evaluate the GitHub, at least evaluate as your next CI. And now moving to the next topic, which is testing library. Well, probably everyone here heard about React testing library. I learned recently that it has sisters, which is X testing library for Cypress, for Puppeteer, for almost any UI framework. And if you're not sure how popular it is, recently, the state of JS big survey was published. And people chose a testing library above Jest and Mocha as their most popular testing framework. Of course, it's not the same thing. But it's, I mean, it was called as the most trendy testing library of past year. And surprisingly, we have the creator here, Ken. Question for you. So I know Cypress. I can do things for this with Cypress. I know to build stuff. And I'm going to start now a new project. Why should I use, for example, Cypress testing library and not Cypress? As is. Yeah, well, I mean, I think you should use Cypress for sure. So testing library is a collection of utilities that you use within testing frameworks. So it's not a replacement for Jest or Mocha or Cypress. It's more of a utility that you tack on to those things. And so like, but that said, with Cypress in particular, there are built in commands that you can use instead of what you get from Cypress testing library. And so the reason that I can suggest adding in Cypress testing library instead of using like Cy.get, for example, is because it gives you more confidence. And that's all that we're really after. I know that some people, some testers really like to use testing to kind of enhance their design process and everything so they can build out their code. And that's great if that's what you want to do. You know, TDD is awesome, whatever. But for me, I'm mostly, and when we talk about running tests in CI, the types of tests that I want to run in CI are the types that can tell me, can I ship this or not? I want, everybody says, don't ship on Fridays. I want to be able to ship on Fridays. I want to ship whenever. Whenever I commit code, it should get shipped. And for me to be able to do that, I need to have confidence. And this is what testing library offers is a really nice way to not only query, in Cypress, it's pretty much just for querying, but elsewhere, it gives you not only query ability, but also interactivity with that output DOM. And the reason I say you don't need that for Cypress is because Cypress has great interactivity functionality already. So it just adds the ability to query your document really, really well. And not only does it make it easier to read and write those tests, but it also, you end up with more confidence because of the types of things that you're writing in your tests. And so, yeah, that's the reason. It just helps you increase the level of confidence. That's the most important thing. Mm-hmm. So just to make it even clearer, so the main motivation for me as a developer is to use testing library across different UI framework is mostly to reuse my knowledge that the syntax that I'm already familiar with, or it kind of pushes me towards best practices. Things like, hey, test like the user, don't focus on the internals. What exactly? Yeah, exactly that. So the fact that you can use testing library wherever you can find a DOM is a really awesome thing, but that's not why you use it. The reason that you use it is because it helps separate your tests from implementation details, which is why you get so much confidence out of it. And originally, when I wrote testing library, it was actually React testing library specific to React. And then I realized that there was just a very thin integration layer between React and the rest of the DOM. And so I extracted all of that. And then we made Angular testing library and Vue testing library and Cypress testing library. There's a test cafe testing library. Like anywhere you find a DOM, you can use testing library for it. And that actually is a huge benefit. So you can have your unit and integration tests that are maybe running in Jest or wherever, and they're all hitting the DOM. And then you can also have your end-to-end tests. And they look very similar from the way that you're querying and interacting with the DOM, which I think is a huge benefit too. Sounds like a great opportunity. And where can, I mean, can you recommend resources, places to learn more about testing library? Yeah, testingjavascript.com is a pretty good place to learn it. And I did share in the Discord a short URL. Maybe I'll share it again because people are pretty active in the Discord. But yeah, for a 25% discount to testingjavascript.com. But of course, it's not the only place to learn. Like you said, it's very, very popular. There are tons and tons of courses that you can pay for, and also videos that you can watch on YouTube. I've given many talks. I've got lots of free content on my blog. And then the docs are really good. So you can go to testing-library.com and learn more. I personally really like this approach of test from the user perspective, almost as production. And I think that this mindset also inspires many now of the testing strategy of the organization level testing strategy are being disrupted. So let's play a small role game. Let's say that you are the chief testing officer or the CTO, and I'm your developer. And I'm working traditionally. Well, I'm writing unit tests, a lot of unit tests. Then after three weeks, when I have the version working with 100% test coverage, then me and the QA person starts writing some integration tests, and then some end-to-end testing, then manual testing my version and put in production. Now we have a meeting and we do our planning for 2021. What exactly, and Oren, let's start with you. What exactly should I change in this approach for the next year? So when you start planning, I think, first of all, you need to understand what you have and how do you want to, we all know the pyramid, right? And we all say, this is the amount of tests that we have unit tested. Unit tests is not enough. They can even, even deciding on over there, everyone tries to reach the 100% test coverage. Code coverage is really hard. It's really hard to get to 100% code coverage, and sometimes it's not worth it. So you have those different layers and you need to decide how to start. And sometimes, by the way, if you don't have anything, sometimes it's even nicer to go actually against the tradition and actually start from the top. End-to-end testing and the integration tests give you high coverage, very, very fast. And they give you a lot of confidence, as you said, close to production to understand, or you can even test in production to understand what you got. The other thing that you need to make sure is that you don't neglect those other layers and you need to make sure that you keep investing in them because they give you the feedback faster. So the end-to-end are super critical. They give you high confidence and high coverage in seconds, where they usually... The challenge over there is what Kent said, and I totally agree, is the trust. You need to trust your tests. If you have tests that are running and you don't trust them, I don't want them. I prefer 10 tests that give you 20% coverage and I trust it, then 100% that it's flaky. And when the CI would go, I was like, oh, it fell again. I don't know why. And then what happens is people take tests out and they say, I don't trust it, let's take it out because I want to release. Or they're starting this thing called rerun. You know what? Let's run it again and again and again and again. Let's rerun until everything passes. And that, of course, it covers a lot of bugs that you don't catch because of those flakiness. You might have a real bug. People think that bugs are only deterministic bugs, that you're saying, hey, I caught this and this will always reproduce. The most challenging bugs are the ones that don't reproduce all the time. When you have that once out of 10, it's going to happen. And you can't ignore that. I keep telling people, if you had someone, like something happened, a robbery, you can't say, oh, the robbery, we're not going to go up in the same place again. You need to make sure, how do I find the person that did this? How do I find it? And that means how they had all the information. And that brings us to the root cause analysis, understanding you need to invest in the fact that you'll know when something does break, what happened. Do I get, is it, we started with the screenshot, then the DOM, I want to see the DOM, the network request, the console logs. I want to have all the information I need so that when something does happen, I know I can pinpoint and say, OK, this is it. And of course, the more you go up the DOM, it's harder to say, to pinpoint. And as you go more to the, more even toward the unit test, you can say, oh, here's the function that, the method that went wrong. This is the state. So here it gives us, up to here, we see a very, we have a lot of coverage, slow response. That means it's harder running on every commit and going down, making sure that we have the amount of tests in each part to know exactly as fast as possible what went wrong. Yeah, yeah, that makes sense. The wider your tests are, then you need more to invest in setups that prevent flakiness and yeah, makes tons of sense. Jason, many of your work is related to flakiness. I'm curious about your overall thought, but also specifically to this, flakiness in integration test. Yeah, flakiness is a big problem. And, but it's also kind of a fascinating field as well. Something I'm sort of weirdly interested in. I can sort of say at Spotify, we had kind of a large flakiness problem. That's kind of how I got introduced into working and testing to begin with. The library that I wrote, JestJUnit, the entire reason I wrote it was because I was working on the Spotify desktop client at the time. And we were trying to tackle test flakiness, trying to reduce it significantly. And so the first part in doing that is just basically knowing what tests have run, which one failed, how fast are they, et cetera, et cetera, putting them in a database and sort of trending these things over time. This is kind of the fundamental starting point for just understanding what is flakiness, like what is flaky? And then how are you going to address this? So it's a fascinating field. There's probably tons I could talk about way more than this conference, but I guess kind of getting to the original question, something I feel that's important to say is that far too many organizations that I've seen, even now, but particularly in the past, don't really recognize the fact that testing and sort of quality in general actually speeds up teams. So there's this concept in Agile called sustainable pace, which I don't know, I just don't see a lot of teams actually following this or really understanding this. A lot of teams are really moving very fast as quickly as they can. And this often means writing no tests or writing fewer tests. But if you can move just a tad bit slower and focus on quality and keep that quality high, this actually pays dividends over years and years and years. So this is something that I think is important, not just to developers, but companies as a whole. I think that one of the big things that we actually see is actually that developers do own quality. Yoni, you mentioned, hey, there's a QA person that's going to say, hey, what's up? I think it's becoming more and more that developers own the quality and they need to say, hey, I feel okay with releasing on a Friday because that means that you feel secure enough. You're saying, hey, I trust this test. It's not someone else's job to make sure everything works. That's my job. That's my responsibility. Sure. Sometimes it's a good idea to release on Fridays. I would like to add that I feel like quality is not, you know, moving it to having developers be responsible for that is not enough. I feel like it's an organizational thing that everyone needs to be aligned on. And I think that's where your quality strategy really becomes impactful is when it actually helps your whole organization understand what quality means. And that's what enables you to actually move forward and be able to have those confidence in those tests, which is why I think test coverage isn't always reliable to do that because it's often just expressed as number of tasks or a percentage. And it doesn't really at all speak to what they actually do, especially for those people who are non-technical or really removed from the day-to-day code. Like what is this test case actually mean in terms of, you know, how does this safeguard my business? And it doesn't say any of that. So a lot of the things that I think is actually important to consider besides test coverage or what type of test you're writing is actually be able to identify, you know, features and flows are actually really high impact areas or high touch areas for your users, whether that's like a dashboard or a homepage or a checkout flow, and really concentrating your testing efforts there, focusing on a few high impact ETE tasks. That's what's actually going to give you confidence, you know, understanding your users. Are they on Chrome? Are they on, you know, desktop versus mobile is going to help narrow down what browsers you're actually going to be testing on. Does it make sense to run all your automation tests through every single browser? So a lot of those things, I think, is more important to think about than just the number of tests. And then again, like that part about communicating about your quality strategy and having everyone within the team and company understand that, I think it's often overlooked, but it's super critical. Yeah. Yeah. And there is a repeating concept here. Start from the user, focus on the user. Okay. We have five minutes left. So I think that it's absolutely now a significant trend to move from Pyramid to something that is more Diamond or Trophy or Honeycomb. Start with integration test or end to end. By the way, some of the earlier TDD books actually also recommend this. Start with wider tests and then do your unit and TDD stuff. But now as a developer, we all know praise integration test. When should I write now unit tests? And also I keep hearing about the new thing, component tests. Kenneth, I'll direct first the question to you. What exactly is component tests and what is the new role of unit tests? You know, it all comes down to confidence and how much confidence you can get out of things. And if you unit test, let's say that you get a hundred percent unit test coverage, you can still have so many integration problems. And so you get a lot of problems there. So let's say, all right, nevermind, we won't do a hundred percent. Let's do like a mix here. And then as you start doing more and more integration tests, you realize that you don't need as many unit tests because you're already covering that code from your integration. And so when you keep on down this path where you end up finding most of your unit tests are in those maybe like pure functions that are doing complicated logic. And those typically they run really fast and they're pretty straightforward to write and maintain. And that's where I find myself doing most of my unit tests. I actually don't find myself doing a whole lot of module mocking in those types of tests either. So I'm pretty much doing component or integration tests. The component is like React component or Angular component, whatever. Integration would be like on the node level, you're integrating a bunch of your modules and stuff. And so, yeah, I find myself doing mostly that sort of testing. And then I fill in the gaps for like these hardcore computational or like these algorithmic things that are difficult to cover with the broad brush of a integration test. Yeah, so it's still a room for unit test and this should be stated clearly. A question to backstage. We're almost out of time, but we have a lot of fascinating topics still uncovered. So if we can get five minutes more, please let me know. I'm moving to the next topic, which is it's a promise for years that it's going to affect the testing world. And maybe this is the year where it's happening. I'm referring to AI based testing. Oren, you are the chief, the guru at testing. The testing I know is a lot about AI. Question, I mean, can you explain really in a layman terms, what does it mean to me really in simple words, features, how can it augment or help testing? We're trying, I think what everyone is trying to get to the same thing, to trust your test. So you can look at it like often, like offering the test to have as much coverage as possible. And I think Nancy said it in an amazing way. Wait a second, how do you define that? How do you see that? I hope that one day we'll get to talk about not just code coverage, but also user coverage. Not just the shift left, shift right. What do we know about production? What do people interact with, what do not? So first of all, AI can help with the offering. Can we generate, can we look in production and generate automatically a thousand end-to-end tests in two days just by looking at what's going on in production? Can we filter out of that? What are the tests that we do want to keep as an end-to-end test? And of course, generating those integration component or even unit tests, can we remove the flakiness? Right now, things like they are basic in every platform was, hey, was one CSS selector. There's one way to find an element and click on it. A machine can look at thousands of them. So can we do that automatically and reduce the flakiness if we understand that a machine can find an element better than us? Yeah, like identify selectors. I identify selectors from previous records that lead more to flakiness and- Exactly, and improve that over time. Yeah, makes tons of sense. I would love to discuss it for at least 10 minutes more, but we are just almost out of time. And I want to cover the last very important topic. Sorry, Jason and Nancy, only one minute to cover this. There is a big bloom of tools that's related to network interception, network mocking, a lot of new capabilities. You specifically, Nancy, wrote one of these tools. Can you first explain to us why it first record the network? So I wish I had more time to talk about this because I think it's super exciting. But I think the biggest thing that the network mocking really solves is it takes the most difficult part out of being able to write integration tests. I wish I can go into elaborate what I mean by integration test because I think it's like one of those testing that's super misunderstood and no one really aligns on what it does. But I think it really solves that flaky issue that Jason was talking about. You can really focus on things that you can actually visually see, things that's as close to possible as what the users can interact with. And I feel like network mocking really allows you to be able to kind of do that without making it super slow and flaky and it cause all those issues. The plugin specifically that I worked on, it actually tags on what is out of the box already from Cypress. A lot of you who do use Cypress knows it comes with a lot of mocking capabilities and it kind of just tags on top of that to really solve for I think the biggest issue with all of this, which is how do we actually manage our mocks? Mocking is obviously number one issue, but number two, once you're able to mock, how do you manage hundreds of files of mocking that needs to change often? And that's where the plugin Cypress auto record that I wrote really helps to address that. But again, I love to continue this discussion. I know we're out of time. Yeah, happy to talk with anyone on Discord. Yeah, I took a look at it and it looked amazing. Like very fast at your integration in practice are a few things they are. We got one last minute, Grace, Jason, I'll really be glad to hear your take on the network interception monitoring. Yeah, sure. Just really quickly. I mean, I think it's an important part of testing. You have end to end tests and the most typical reason why they're flaky or why they're slow is going to be network requests. So if you can kind of take those out of the equation, especially if you have something like VCR where you can automatically generate stable mocks, you turn these end to end tests into something that is far less flaky and far more performance. And basically it's testing the same thing using hopefully the same system. So there's a lot of benefits to it. I would encourage you to look at it, especially Nancy's plugin there is a pretty great example. Yeah. Thank you, Jason. And unfortunately we're out of time. So really many thanks to all of you for this great insight. Should I try to summarize it in one sentence? It's production user, production user, production user, leave the internals to the end, start from the chaos of production, the network from the user, from the UX. This is where most of the tooling now innovate and this is where testing should start from. And then if you have something complex inside, then well, we have the traditional unit and other tools. Many thanks for all of you for being with me today. Thank you. Thank you. Thank you. Bye.
Fire-Side Chat with Kent C. Dodds
React Summit Remote Edition 2021React Summit Remote Edition 2021
31 min
Fire-Side Chat with Kent C. Dodds
Hello. Hey Kent, how are you doing? I'm doing great. It's a beautiful morning here in Utah, kind of rainy, but my wife likes the rain, so I'm happy. Happy wife, happy life. And of course, happy kids with managing four kids. Like I said, crazy managing that with your career. I know that you are really happy with your kids, and I'm also happy with my kids, of course, but how are you managing now with the pandemic? They're probably more at home and managing your career. Is that difficult or is it okay now? You know, I was already doing a lot of remote stuff before the pandemic hit, lots of remote workshops and things. And so the pandemic didn't really impact my career a whole lot in that regard. I mean, everybody was impacted and my kids started doing school at home and everything, so it shook everything up. But yeah, I wasn't impacted as much as everybody else. Good to hear that. So as much as I would love to talk about your kids, I also have a son and yeah, like to talk about it. I think our audience is not here for talking about your kids. They want to talk about testing. So a few weeks ago, we've sent out a tweet that people can ask some questions that they want us to discuss. And the first one is from Peter Hozak. You are migrating some of your projects to TypeScript. What are the biggest pain points for you so far? And what can you recommend to the people or teams who are not yet decided whether to start the migration in their projects? How time consuming would you say it will be? So it will be relative to the size of your project and the experience of your team. So I can't really tell you exactly how time consuming it would be. Migrations are always really tough. You have to take that with a grain of salt. I actually have a blog post about engineering and business alignment and how important it is that you do what's best for the business, not just what you want to do. It's actually a pretty good blog post. You can go take a look at it at kentcdots.com. As far as like recommendability, I definitely recommend it. I think it's a great idea. And there are some strategies that you can use. And to be clear, I haven't ever... I'm trying to remember. I think we actually did migrate one of our projects at PayPal to Flow. And that was in process as I was leaving. But here are a couple of tips. So first off, it doesn't have to be perfect, especially if you're just learning TypeScript. So I would not turn on strict mode. It's actually similar to adding ESLint to a project that's never had Linting. I wouldn't recommend enabling all of the rules and fixing it all in one giant PR. But rather disable most of the rules. And then over time, you add them as warnings. And then you fix things here and there. And then you turn them on as errors or whatever. So in the same way, just make your TypeScript really loose at the very beginning, especially if you don't know TypeScript very well. You don't want to just spend a ton of time writing your types and they end up misleading you. And you write it poorly because you're new at TypeScript. So throw an unknown there. Throw in any here. Whatever you need to do to get it going. And then come back later when you know TypeScript better. So yeah, I would recommend it. It will take a...I would recommend it iteratively over time rather than just one giant PR. But yeah, I think it's a good idea. Yeah, that's also my experience. Going with a big bang. I mean, besides that it just takes a lot of work from you. You're going to send that PR to someone and he's going to be your archenemy after that, right? So if you want to keep friends with your colleagues, then don't do the big bang. Even if it's a small project, migrating to TypeScript, even though it's really valuable, it is a lot of work and yeah, don't go with the big bang strategy. Next question is... You're going to make a different story. You're going to big bang prettier all day. Next question is from Bazaat. Nowadays that Next.js looks so solid. Should we use Next.js instead of Create React App or Create CSR? I'm not sure what CSR is, but yeah, so Next.js is solid. Sorry, I'm going to stop you for a little bit. And I want you also to chime in if you're going to Next.js on the vendor login. Oh yeah, sure. So yeah, Next.js is solid. I used it years ago. I haven't actually used it recently, but a lot of people use it and they love it. And yeah, so I don't think that you can go wrong with using Next.js as a framework. I'm really, really excited about Remix personally. For the last several months, I've been using it to totally redo my personal website. I'm really excited about a big rewrite that we are working on. So that's what I'm working on, but it is still developer preview. It has features that you won't find anywhere else. And that's what's compelling about it for me. It's not just like a paid version of Next. It's very different from that. Although a lot of people like to say that without any experience with Remix. So yeah, but Next.js is totally solid, if it looks interesting to you, then go for it. And do you have your Remix project in production also already or is it in development still? It's still in heavy development right now, but we're talking like a month or two before it comes out and it'll be pretty sweet. Nice. Well, looking forward to that. Probably you'll announce it on your Twitter and all your channels, of course. Oh yeah, yeah. You won't miss it. If you follow me on Twitter or subscribe to my newsletter or something, you will definitely hear about this. Yeah, I know when you do something new that it's hard to miss. That's a good thing. Because I always like to see what you're doing. So wouldn't want to miss it for the world. Next question is from Carlos. Is the testing library a new mindset for front-end tests? I mean, we will think about user behavior. So maybe it's not to test some component like a button or even hook and test it integrated in a page. So it's more like, yeah, kind of like a Cypress test that you're really going through a flow. Yeah. So I don't often test lower level components that don't have very much logic into them because it's so easy to cover those things. Like if you have a little button or something, like you would not find me testing a button unless there was some fancy complicated logic that I wouldn't easily cover in a higher level test. I have a blog post about this as well. You can find it at kcd.im slash trophy where I describe the different layers of the testing trophy. And one thing that I say in there is actually I'm quoting an interview that's on testing javascript.com where it's basically testing these different layers of testing are kind of like painting a wall. And the quote is you can throw paint against the wall and eventually you get most of the wall, but until you go up to the wall with a brush, you'll never get the corners. And so, yeah, like your end-to-end test, that's like just taking a bucket of paint and throwing it at the wall. But eventually you need to go with more fine-grained tests and maybe you've got like a painting that's your grandma made it or something and you don't want to even paint with a big brush. You'll take a smaller brush around that. And so that's kind of the way I think about different layers of testing. There's no reason to take a small brush to paint the entire wall. It will take too much time to get full coverage. But yeah, so I focus more of my time on integration tests like that's a paint roller. You cover most things really well with that and certainly end-to-end tests as well. But you can use testing library for all of these. That's the cool thing about testing library. Anywhere a DOM can be found, a testing library can help you to query for elements and interact with those elements. When you were mentioning coverage and I don't think there is a real answer to this, but we can ask it anyway, see what your thought is. What's a good coverage for most projects you would say? Would you always say 100% or? Yeah, I actually would assert that 100% is a bad coverage number. Maybe not as bad as 0%, but yeah, still a bad one for most of the time. Now if we're talking about an open source library, then yeah, sure, 100% that's typically relatively easy to accomplish and there's a high value for that because this is highly reusable code, right? So it's a little bit different. But for applications, if you're shooting for 100% coverage, you typically end up spending a lot of extra time testing things where you'd get a higher return on your investment working on features instead. And so I actually have a blog post about this titled How to Know What to Test. And in that I kind of talk about how code coverage is a useful metric, but a better one would be use case coverage, which is not really reasonably easy to set up as a metric, but it's the way that you should think about your test. So I don't often look at my code coverage report. The only time that I look at that is just to remind myself of use cases that I may not have covered, but I'm always thinking about use cases. What I really like about, well, it's not actually about the coverage, but if you look at that report, I think it's the Jasmine report it's called, where you see your code and then what branches are and are not touched by the code, by the tests. That is a way I really like to go through that and see, oh wait, this is a path that is dangerous that I didn't test it. And then I'd have to ask for that. Yeah, exactly. So that is a good thing. And yeah, like you said, going really for a hundred percent or whatever the percentage is, I've had companies where there was a percentage set and you just know that at a certain point you are going to be writing tests just to satisfy your coverage needs, even though you kind of already know like, this is fine. I don't need to test it, but yeah, my pipeline will fail if I don't test now. So yeah. Yeah. But don't go there. Yeah. Yeah. Next question is from Henrik. What's the best piece of advice that you've received career wise or also in general? What advice would you give now to someone who's in the beginning of their career in tech? Great question Henrik. Yeah, that's an excellent question Henrik. So I think one of the most important things, the first thing I have to say is to be nice. It doesn't matter how good of a coder you are or how good of a, you know, people, well, yeah, you just got to be nice. If people don't want to work with you, then you will not get the work that you want. So if you want to have control over your career and really accomplish whatever goals that you have, you will be able to do that much better if you're a nice person. So then on top of that, I would say communication is a really important career skill because even if you are the best coder in the world, if you're not good at communicating what you've accomplished and how that impacted the business or improved lives for people, then that also will make it difficult for you to get the work that you want. You see this often with people who are really good at something or at least they're the one who doesn't complain about doing something. And so they get all of that work when actually they'd want to do something else. And so you need to be able to communicate what your career goals are and what your accomplishments are. Like you just get really excited about the things that you want to keep doing and you say, hey, look at this cool thing that we did. I'd love to keep doing this. Or hey, this is a cool thing that we did, but I'm not super into that. Could I start doing some more of like the front end side or the back end side or whatever? So communication has been a really, really useful tool for me. Yeah. I love that you're saying that at a tech conference that you don't mention any technology, just be a nice person. And I love that answer. Thank you. I'm going to go look at our Discord channel, what the input is from our audience, the live audience. All right. Oh, I see RTL. I haven't even read the whole question because this is something I just want to know, because what is your experience with testing RTL components? And do you have any tips or any resources you can recommend for people getting into RTL? We've had some talks yesterday also about the internationalization and then I want to get your side, like making it secure. Yeah. Yeah. So Daria gave a great talk yesterday morning on internationalization. So and actually she mentioned my library, RTL CSS JS, which is pretty handy. So yeah, I've never written a test specifically for RTL. RTL is also an acronym for React Testing Library. So maybe that's a little confusing, but right to left is what we're talking about. But yeah, so I've never written a test specifically for that. If I were to, then you'd probably be best. This is like a visual thing. Or I mean, there's obviously there's the actual content side of it as well. Most of my tests or all of my tests use the default language as the content for like querying around for things and entering in texts and stuff. I feel like you just get a marginal improvement in confidence by adding testing for different locales and so that's why I don't bother. But RTL is definitely a feature that you don't want to have break. And so if that is something that's really important for you and your business, then you probably want to go for visual regression testing. And so that's we're talking about tools like Appletools or Percy.io, where they will use their fancy AI to figure out the right way to do visual regression testing. Because I don't know about anybody else, but visual regression testing is notoriously very finicky flaky. And so these technologies have advanced enough to reduce the flakiness of these types of tests. And that's how I would go about testing RTL if that was a really critical piece of my business. Yeah, well, of course, there are a lot of businesses where it matters if you're like the thing I know about testing RTL is the Netflix blog post. It was like two years old and they shared their approach that even when also doing left to right LTR that we're adding, I think, 20% extra characters in every string just so they kind of know for sure that if there's a language where the string is longer that the interface won't break. So I don't know if you've seen this blog post, but that's something if you want to do RTL testing, I would recommend looking up on the Netflix engineering blog, which is also just a nice blog to follow. Percy.io is the one I've mentioned. Question from Luke. Does React testing library get tested itself? How do you test your testing library? Yeah, nice. Yeah, yeah, sure. So you think about it, testing code is no different from any code, any other code. In fact, even the test that you're writing, that's just code. And you could write tests for those. You could take your test function block, you could put that in a function, and you could call that function and make assertions on what it does. So like, it's all just code. And when you're writing a bunch of tests, eventually you come up with some utilities that may or may not be useful for anybody else. And that's what React testing library is. It's a bunch of utilities that I wrote for myself that I thought, wow, these are really useful. Let's make a library out of it. And then teach people how to use it. And that's testing JavaScript.com. So yeah, it is definitely tested itself. It's mostly just like JavaScript utilities. And so it's not, you know, it's very different from a testing framework. But even the testing framework itself is also tested. That's actually even more interesting, because Jest uses Jest to test itself. And so, yeah, that's where things get a little meta. React testing library doesn't use React testing library to test itself exactly. I mean, we are calling render when we're testing the render function. We are calling, you know, get by text and get by role and all that stuff to make sure that it's doing what it's supposed to. Most of the time we're in general, I recommend that your test should resemble the way that the software is used. And so our tests for React testing library do that as well. And so if you go through the React testing library test, you'll probably find some that are for lower level utilities that are like more lower level unit tests that you wouldn't write. But lots of them are integration tests. And so they'll look very similar to the types of tests that you would write. And if our tests are passing, then we assume that we won't break your tests, hopefully. Hopefully. Well, it sounds kind of scary. Like you said, Jest is using Jest to test their code. Because if Jest breaks, will the test also break? Yeah, that's how do you know that? Yeah, I believe that there are some languages that are written in themselves as well. I don't know how that gets started, but eventually they switch over to their own language to write their language in, which is interesting. That's extra meta. We have a question from Sasha. Do you think integration testing is also important in addition to unit testing for component library? And how do you feel about integration testing in general? Yeah, well, I'm kind of, I have a blog post that's pretty popular on this topic called write tests, not too many, mostly integration, which is a quote from Guillermo Rauch from years ago. And yeah, you can take a look at that. It's kcd.im slash write dash tests. And so the testing trophy is weighted toward integration tests. I focus on integration tests. For component libraries, the line between integration and unit test kind of gets fuzzy. Some people say unit test is just the unit. You mock everything around it. And if that's how you define a unit test, then I don't write many of those at all. And most of those are like, I have a pure function. It's pretty complicated. Let's just test that by itself. And that would be my form of unit test. So if that's how you define a unit test, then a component library, I pretty much wouldn't use almost any unit test. It would all be integration. I want to render the component, I want to interact with that component. And yeah, so I focus most of my time in the integration space. So let's go a step beyond component libraries. Let's say you have a design system. So just a collection of components in the end. Would you also be adding tests for a design system then? Yeah. So then you would be testing that button. Yeah. Yeah. And actually at PayPal, I was responsible for building that. That was the last thing that I worked on before I left. And yeah, I was testing every component. But there was always logic that I was testing there. And when it is like a design system or component library and you have a button, I would at least have one test that says, this thing renders. Because it's just so low cost to have that sort of a test. And because it's a reusable design system or component library, I want to make sure that I didn't have a syntax error or something. I mean, it was in TypeScript. So the likelihood of having a problem is pretty low. But then would you say like a snapshot test would be enough? Yeah, snapshot tests. I have a blog post about this called effective snapshot testing. In component libraries, maybe. The thing is that snapshots are just assertions. They're no different from any other assertion. So when you have an assertion, you want to make it so that a failure, when you have a failure, you know why it failed as much as possible. That's your job as an assertion writer. And when you take a snapshot, you could take like a snapshot of the world that could include like where the sun is and like what operating system you're running and like literally everything. And this is the state of the world. And that would not be a useful snapshot test. Of course, we don't do that. Often I will see snapshots that are hundreds of lines long. And so what I'm saying is a snapshot often includes a lot of information that is totally irrelevant to the test. And so I really rarely use snapshots for UI testing. It is very rare that you'll find me doing that. What I do is if I want to start with a snapshot, I will slowly get rid of all the stuff in the snapshot that is irrelevant. So I'll find the element that I'm trying to assert on. And then I'll realize, oh, all I care about is that this attribute is, you know, this certain value. And so instead of doing a snapshot, I'll just make an assertion on that attribute. So yeah, you can read more about that in my blog post about snapshots. Yeah. So if you actually want to, let's say we're going back to a button and you want to test if it accepts a class name, your component for that button, then you can do that with a snapshot. But if the snapshot test fails, yeah, you don't know what you're testing anymore unless you've written a really good description. So it's better to just say it should accept the class name and then, oh, I am failing with my testing library syntax in my head. I was going to write it. Yeah. You just select the button and say to have class name. And then it's very clear. Like I pass it this class name. I expect it to have the class name. If that fails, then whoever's reading it, even if it's me in six months, I know exactly why this failed. I may not, or I know exactly what the object is. I may not know why it happened, but I know what the intended outcome is. Yeah. That's, that's a good point. Sometimes even you're writing tests for yourself. I haven't always been writing tests. I have a quote from a friend of mine, Frank de Jonge, and he once tweeted, I don't write tests. I write proof. And that's always like, I'm proving to myself that this works as I intended. And I really liked that mindset for myself. So that sounds good to me. That's insights. Next, we have a lot of people mentioning, by the way, like go is written in Go, C is written in C, TypeScript is written in TypeScript. So really cool to have that interaction. It's a little mind bending. Yeah. It's too meta for me. To follow up, Juan is asking to follow up on the communication tip, what communication resources would you recommend? Nice. Thanks, Juan. Ooh, practice, I guess. I don't have any resources to offer. I'm sure that there are books and things like that. This is something that kind of comes by naturally for me. Maybe I'm a little on the obnoxious side, but I share everything. That's like, that's why, that's often why people think that I get so much done is because I literally share everything that I do. So I may not be getting more done than anybody else, but I just share everything. Yeah, I don't really have any specific advice. Well, I don't know, this may not be totally related, but one podcast that comes to mind is the Soft Skills Engineering. I really love that podcast. It's hilarious. Just its entertainment value is good all by itself, but they have some really good advice often about communication. All right. So would you mind sharing a link with that in the Discord later on so that Juan can find it and the rest of our audience also, of course. And to follow up from my side, just talk to people. If you want to know if people like you, you'll probably get a fair answer if you just go down for a one-on-one, but it might be scary. So yeah, if you don't like that, I would understand. We have a few, yeah. Let's take a moment. We are reaching the end of our fireside chat. Just to be sure that we don't go over time, let's take a moment to go through the poll results. So Kent has asked what the percent of time you were spending on the different things of testing. And the winner is Hooks, 100%, with 46%. That feels really weird. 100% with 64%, sorry. In Dutch numbers, you say them the other way around. I'm sorry. It's always hard for me. So Kent, is this what you were expecting? Yeah, I've been doing this poll on Twitter over the course of, since Hooks was released, every few months I'll give this poll. And it's just very steadily going in the direction where very few people are not using primarily Hooks. And this is why I totally dropped classes from all of, like class components, from all of my teaching material as soon as Hooks came out. I was like, I'm done teaching that. You could go look at my old stuff if you want to learn about classes. I am 100% Hooks everywhere now. Yeah. Well, that's good. You got to keep up with the modern stuff. And you don't want to write something that people are not using anymore. So that's great. Right. I also remember- You want to stay up to date. I also remember that a few months, or maybe it's over a year ago, you asked if you should write TypeScript for your material, right? On Twitter. Yeah. What was the result on that? What did people like? Yeah. Well, sometimes I do polls just because I'm interested in what people say, not because I'm going to change what I do. So yeah, I kind of do what I want. And the people who are cool with that will follow me along. But yeah, so I am definitely doing TypeScript for all of my stuff. I already have a... I'm in the process of obtaining all of Epic React to be in TypeScript 100%. I'll have to rerecord all 350 videos for that, which will not be fun. I am going to make a TypeScript course or a series of workshops for people. So if you haven't done TypeScript before, you can go through that. I also already have a script that'll remove all the TypeScript. So if you don't want to do TypeScript, you can do that too. But I just think that TypeScript, it makes even the learning experiences better because you get auto-complete and it just, that's an enormous benefit as you're learning. So yeah, TypeScript all the way. All right. Great. Another question from Luke. One minute, so be quick. What are your opinions on linting your tests? I lint my tests. There's a linter plugin for testing library that you can take a look at. I think there's actually... Yeah. So I would recommend using that for your tests. It helps you write better tests. And yeah, I absolutely lint my tests. I also write my tests in TypeScript. It can be kind of annoying sometimes, but you kind of figure out clever ways to, especially like with mock functions and mock modules. But yeah, I recommend typing your tests and linting your tests. Wow. I was not expecting that, to be honest. Well since that was our last moment, my memory is slipping, but do you have a speaker room available? Are people able to continue the conversation? I'll be in the special chat for folks to chat with right after this. Awesome. Well, that's it for our little fireside chat, Kent. Thanks a lot for joining. I had a lot of fun and yeah, unfortunately I can't continue in the spatial chat because I'm needed here. But yeah, hope to see you again soon. Yeah, likewise. Thank you so much. Take care.