Web App Testing & Tools

Common Excuses for Not Testing

Miško Hevery

Miško Hevery

Qwik Creator (Previously Angular)
Web App Testing & Tools

Check out a free preview of the full Web App Testing & Tools course

The "Common Excuses for Not Testing" Lesson is part of the full, Web App Testing & Tools course featured in this preview video. Here's what you'd learn in this lesson:

Miško discredits the common excuses for not including tests in a codebase. Often, omitting tests is not because of time or scope of work but a lack of knowledge for writing effective tests and having the tools in place to execute them.


Transcript from the "Common Excuses for Not Testing" Lesson

>> So, I wanna ask you a question and that is, why don't you test? Who does testing here? Everybody? Okay, one person is not raising their hand. [LAUGH] Why don't you test?
>> Sometimes just not testable you have some async personality and Yeah.
>> Well, we don't have time.

We'll build it now and we'll test it later, which I mean, I don't agree with that at all. [LAUGH] I hear that a lot.
>> One thing that I run into is working with a legacy code base that there's just a ton of problems. [LAUGH]
>> Yeah, yeah.

>> So, as much as I'd like to write tests around it, figuring out how to do that can be a real challenge.
>> Yeah, legacy is tricky. Yes, that's a topic of itself. So I have this kind of a chart I made, like why don't people test? And these are random different excuses.

And I have this green thing on the top that's like semi-valid excuse, and we pointed out legacy code base, right? That's kind of semi-valid, but it's valid in the sense that it is difficult. It's not valid in the sense that you don't have to do it and you shouldn't do it.

You might have a much harder time writing legacy part, but it is something that still you should strive for. Writing a UI test is also a little tricky, but we're actually gonna talk about that today. But I wanna go over some of these other arguments. One is people say, well, it dirties the design.

And I'm gonna try to convince you actually that, actually no it makes the design better better. Right? Because fundamentally what testing requires you to do is to assemble the system in a different way. Right? Like if the code base you have can only be assembled in one particular way which runs the application, and you come in from a testing point of view, say, well actually, I want to assemble it in the smaller chunks.

That means that actually it's less coupled because it gives you the freedom to assemble it, not the whole app, but a portion of it and run the portions of it independently. So that actually makes the testing easier. Now the reason people say dirty is designed is because if you have a legacy code base, it is so intertwined that trying to get it to a testable state, you might temporarily have to kind of hack things, too, in order to make them work.

Mark, did you have a question?
>> Yeah, a couple of people online said when approaching a legacy codebase, it's difficult to figure out where to even start testing.
>> That is very true. Legacy codebases can be almost impossible to test. And what it comes down to is managing the dependencies.

And we're going to talk about that sometimes later. But that's like the knowing how to test legacy codebase, that probably is a course on its own.
>> Somebody else said, sometimes I have a database dependent situation that also involves specific date/time variables. I guess it's difficult.
>> So marking time is important part of the particular thing.

People will sometimes argue that the testing doesn't catch bugs, which is kind of a strange argument for me because it's kind of the whole point of it, and especially once you have lived in a code base that has good tests and you refactor the code base, you realize just how invaluable it is and you realize like, how did we used to write code before testing?

Like, I remember when I used to write code before test and I have no idea how I get anything working. People argue that it's slower because you have to do more work. So it is true that with tests, you will do more typing, because you have to write tests, right?

But I actually think it is faster, especially once if you start a new project, you write lots of code fast, but that quickly kind of tapers off, and you get into kind of a maintenance mode, right? And it's in the maintenance mode where tests really start to shine because you think you're fixing a bug so you change something and unless you have all the previous tests and all the previous assertions, your fix might very well be breaking three other things.

And so the amount of time you save not regressing is actually huge. Okay people say it's boring. I actually think it is fun once you're doing it the right way. We'll talk about that more in the future. People often argue that if you make a lot of tests, the codebase becomes hard to change.

And I see what they're coming from. They're basically saying that the tests assert the inner working so tightly that any kind of change to inner workings would require you to change the test. There is a little bit of merit in it, but it all depends on the kind of test you write.

If you have tested essentially what I would call a snapshot test, a test that takes a snapshot of the system and basically any change to that snapshot is considered a failure, those tests are not very useful, right? And also become very difficult to change. But if you do it correctly and you have intentions in your test saying like, hey, when this is the input of the system, then I expect this particular output.

And I specifically don't care what happens in the middle, it's a particular kind of test, then in that case, it becomes easy to change the internals because the test isn't asserting about how you're doing things, it is only caring about the particular outcome. And so whether or not your system becomes hard to change, it really comes down to how strong you are about these.

Making assertions about how it does things, right? If you're gonna micromanage the software into delivering the output that you want, then yes, you might get in a situation where these tests are overly protective of the changes. But if you do it as in like, look, I don't care how you get there, I just want to make sure this is the output, then the test actually become much easier to deal with.

Writing tests sometimes does mean that you have to create interfaces. Now in typescript and in JavaScript, interfaces are not really much of a thing because everything is duck type so it's not a big deal. In other languages like in Java or more strongly typed languages. Interfaces are more of a thing.

But yes, interfaces are a useful way of allowing you to manage your dependencies. We're going to talk about that later. The other one people often talk about is, hey, testing is for QA. Like, this is not my job to do testing as a software developer. We're going to talk about more a little later, but I really want to point out is that testing is actually very much the job of the developer.

We need to adjust our assumptions about whose responsibility these things are, mainly because testing isn't that much about writing tests, it's about designing the code-base in a way so that it is testable. If you design code in a way that is untestable, there's very little that somebody can do after the fact to add tests.

In other words, if you design your code in an untestable way, you've essentially created a legacy code base. That's the reason why legacy code bases are difficult to test, is because, well, they weren't designed with testing in mind. So there's nothing inherently difficult about testing existing code, as long as the code is written in a testable manner, right?

So, in a strange way, we're gonna be talking today mostly about what do you need to do to make the code testable, not about how do I actually test, right? So I'm not here to teach you how to test, even though that's the title of the session, rather, I'm here to teach you about how do you structure the code so the testing becomes easy.

And that's a very different way of thinking about the problem. Now, one of my favorite excuse, which nobody ever says is they don't know how, right? That is fundamentally the reason why people don't test, right? Because they don't know how. And it is not obvious that, hey in order to test I have to design my code base in a particular way, rather than knowing the insides of how to write tests.

Everybody's always thinking like, if I just install some special piece of software or whatever, my testing will become easier. And the answer is no. It's all about designing the code in a testable way. And knowing how is a skill like any other skill. Now what I find interesting about this is that you can come to a developer and you say, Hey do you know Rust?

And they'll say no I don't or whatever. And they won't feel any hesitation saying that they don't know how to do this particular thing. But if you come to a developer and say do you know how to test? Even if they don't, they feel bad about saying that they don't know how and they will essentially lie and be like, Of course I know how to test.

I find this really interesting that somehow a skill of testing is not the same thing as a skill of a particular language, which is perfectly fine to admit that you don't know. And I think we should get better at it. We should be able to freely admit saying, look, I'm just not an expert at this particular thing and I wanna learn more on how to do this.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now