Check out a free preview of the full Testing Fundamentals course
The "Testing for Edge Cases Exercise" Lesson is part of the full, Testing Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:
Students are instructed to write tests for the subtract, multiply, and divide functions to handle different types of input. After writing each test, the function implementations should be updated so the tests pass.
Transcript from the "Testing for Edge Cases Exercise" Lesson
[00:00:00]
>> Steve Kinney: So what I'd like to challenge you to do is a little bit of exploration time, which is, we've got a bunch of other math functions in there. Then there's just basic stuff like, what happens if you divide by 0? Do you wanna throw an error? Do you wanna return NaN?
[00:00:11]
You make your choices, I don't care. But we've got a bunch of math functions. We got a whole bunch of garbage you can pass into those, right, you get to decide what they do. You could sum up an array for all I care. You could call the function, for all I care.
[00:00:24]
You choose what you want to happen. And hopefully, you'll either come up with stuff where that's pretty clever, or b, you'll come up with something you don't actually know how to test or implement. And then we'll kinda take a look at that together and come up with all of the weird things that stump you.
[00:00:40]
And then we'll look at them together and see if we can figure it out.
>> Steve Kinney: All right, so our mission was to figure out other edge cases that some of these very humble functions might have. Anything from, what happens when we divide by zero, to what happens if I throw one of these garbage values in there, right?
[00:01:03]
For some of these things, there's not necessarily a right answer of what should happen, sometimes it's what you should decide to do. You could be like, hey, if one of those arguments is undefined, default it to zero. That's a fine decision, right? And one of the nice things about your tests is, cuz the only thing developers are worse at than testing, writing documentation, right?
[00:01:25]
And so a lot of times, the act of having a test that says what should happen if undefined is passed in. If I am then going and refactoring that code later, or looking at it, it shows the intention that this is doing something for a reason because you wrote.
[00:01:41]
It should default an argument to zero. Now, I might disagree with that, or I might agree with it, but at least it has also gone the extra step of making your intention explicit as well, right? Did anyone come up with any? I'll invite, particularly, compelling ones, but I'll just go for regular ones too.
[00:02:01]
Any edge cases that we should work through?
>> Student 1: Arrays were interesting to me.
>> Steve Kinney: Okay, we can do an array, like we picked the challenge mode right out of the box.
>> Student 1: [LAUGH] What crazy things people do with arrays and expect it to do math for them?
>> Steve Kinney: Yeah, so let's see.
[00:02:20]
What should happen if I pass in an array?
>> Student 1: Or do that add one?
>> Steve Kinney: Yeah, or we'll do it any one you want.
>> Student 1: I was looking at subtract cuz I was looking at the [LAUGH] subtract.
>> Steve Kinney: Cool, all right.
>> Student 1: I know, I made it hard.
[00:02:31]
>> Steve Kinney: What should happen if I pass an array?
>> Student 1: And then I thought, did I just write myself a code war, SCADA, or whatever the?
>> Steve Kinney: Probably.
>> Student 1: The code problem, I think I did.
>> Steve Kinney: Let's figure it out.
>> Student 1: So [LAUGH].
>> Steve Kinney: It should.
>> Student 1: So the easiest one would be to throw in an array [LAUGH].
[00:02:48]
Give me an array, no, but.
>> Steve Kinney: It should, let's say, it should.
>> Student 1: If it accepts arrays, I would say it should subtract.
>> Steve Kinney: The art here is making sure this statement actually says what it should. It should accept an array, like, uh-huh, and should accept an array and.
[00:03:07]
>> Student 1: Subtract [LAUGH].
>> Steve Kinney: Subtract all the numbers.
>> Student 1: The numbers down the line [LAUGH].
>> Steve Kinney: Yeah.
>> Student 1: And then subtract the two results from each other [LAUGH], cuz I don't know.
>> Steve Kinney: Well, the interesting part is, we can break this out into a few different-
>> Student 1: That's where I was like, yes, I just write myself a lead code problem.
[00:03:25]
>> Steve Kinney: So we can say, expect, subtract, and let's just start with 2. Let's say, 4 and 2, because I don't have a use case. It's about isolating that code into the one thing you wanna test at this point. So let's make that number a little bit bigger. We'll say 10, we'll subtract 5, and then we will subtract 2.
[00:03:57]
10 minus 5 is 5, minus 2 is 3, right? Cool, okay, and the letter b is not gonna be good enough here, so we'll run that. And I've got a failing test, right? Cuz we get not a number because it is trying to do that thing. So now the question is, what do we do here?
[00:04:17]
All right, we're going to subtract and we'll say, if.
>> Steve Kinney: Array is array a, a = a.reduce.
>> Steve Kinney: A is b, and then we'll return. And the nice part is, I don't have any idea if this is what I want. My test pass. Yay, I know how to code, right?
[00:04:58]
And so now I've got that kinda captured in there as well. But again, it's nice till I sometimes see that one. I now know that if a argument is passed under the race for the first argument, exactly what will happen. And effectively, it's also codified in my test if someone comes along later and wonders what this thing could take, right?
[00:05:17]
And there's other versions of this. What would happen? The one I was kinda thinking about is, sometimes you'll write a test and you will get stuff for free, right? So I know if I throw in potato, I'll get a yelling at that's not a number, right?
>> Steve Kinney: It should throw if the.
[00:05:41]
>> Steve Kinney: Not a number. In my assumption, I literally didn't write this during the breaks, I don't really know, but my expect, there we go.
>> Steve Kinney: Right, and that works as expected. But now I have validation that both a string that I can't turn into a number, and not a number will both throw the same error, right?
[00:06:12]
And this is useful in the case that I decided to refactor and change this logic somehow, right? Cuz again, there's so many edge cases, right, that what I don't wanna do is, all right, next up, I'm gonna decide what to do if it's a Boolean, right? And then I change this logic.
[00:06:32]
Now it'll probably work cuz it's simple, but I don't know. I've moved on from thinking about strings, right, now I'm thinking about Booleans. But the nice part is, if I accidentally break a previous problem I was trying to solve, guess what? I will know immediately.
>> Student 1: How about additional missing parameters?
[00:06:49]
>> Steve Kinney: Yeah, and so again, we set up our tasks in this case, right? When you wanna do an add, you wanna do it and subtract, where are you feeling?
>> Student 1: I don't care, it doesn't matter for that.
>> Steve Kinney: Let's go with subtract, it doesn't have a lot of test.
[00:07:08]
>> Steve Kinney: It should default undefined values to 0, default it to 0, right? So in that case, we would expect that subtract 2 or 3, and then no other argument would be 3, right? We save that, and my test blow up, right? Cool, and so we need to fix that.
[00:07:39]
In this case, what we could do is.
>> Steve Kinney: Just default value of 0, right, and now it passes. Now that doesn't solve for the first one. And then we decide, should you give me some number whatsoever? Forgetting a second value, likely. Forgetting the first one is a little harder to type, but we could even put that in the same test if we wanted to.
[00:08:11]
>> Steve Kinney: Be -3, right? Okay, doesn't work. And again, that's that kinda flow of, we all deviate from this at some point, right? Cuz it took every ounce of my fiber of willpower not to just make both of them default out of the box, right? Which is technically deviating from test-driven development, which is why we all do it, because impulse control is hard, right?
[00:08:33]
And now it passes, right? And again, we could do that for the rest of them. Now, again, I don't know, I literally do not know.
>> Steve Kinney: Zero if either argument is null, right? Again, you could decide you wanted to blow up instead, but I don't know. And so you're just kind of figuring out all these things and making it happen.
[00:08:58]
Yeah, Mark?
>> Mark: Andre says the division by zero is particularly interesting.
>> Steve Kinney: Let's do that one, too. So let's say, 3 subtracted null. Expect it to be 3. Okay, that does work. Now, if you want it to blow up instead, you gotta refactor that code because now you can't use the default arguments, right?
[00:09:17]
But the nice part is, you could worry about null and know that undefined is still taken care of, because you have the test for it, right? And you could refactor to say, hey, undefined, be zero, null, I want you to blow up, right? Again, I don't know why you'd want that, but you could.
[00:09:34]
And the nice part is, you're so hyper-fixated on null, you might forgotten about undefined, right? But your test suite didn't, [LAUGH] right? And because your test suite didn't forget about undefined, you won't forget either, right? So then we'll say, null and 3 to be -3, cool? Everything passes, great.
[00:09:59]
All right, so we had dividing by zero. What do we want it to do if we divide by zero, blow up?
>> Student 1: Return null.
>> Steve Kinney: Return null.
>> Student 1: [LAUGH] But you [CROSSTALK].
>> Steve Kinney: Someone want to see the world burn. We're doing it. It should return null, and then we'll do it through an exception too.
[00:10:29]
>> Steve Kinney: Right, cool.
>> Steve Kinney: And now we can say, expect divide 10 by 0.
>> Steve Kinney: You can do this too. You know what that is the same as?
>> Steve Kinney: Same thing, whichever one makes you happier. Okay, that doesn't work because it is technically infinity. I knew that cuz I rehearsed this, there's a bunch of other weird cases in there as well.
[00:11:02]
Did you know an empty string counts as zero as well, right? So theoretically, an edge case that we might have to solve for here is an empty string is zero. Is that what we want? I don't know, you gotta decide. So in this case, let's go get it working, which is.
[00:11:23]
>> Steve Kinney: So then we gotta take, result is a divided by b. And I thought about throwing if b was zero. Now, I guess there's multiple ways I can do this, right? And the nice part is, my test will immediately tell me if I'm right or not, cuz I know NaN does not equal NaN.
[00:11:47]
Let's find out if infinity equals infinity.
>> Steve Kinney: And the nice part about having tests is, I don't have to go sit through my terminal, run the thing, look at the constant output. I'm gonna hit Save, I'm gonna find out that I'm still wrong. Received, undefined. I broke the previous test, right?
[00:12:07]
I broke an earlier test, right, of 10 divided by 2, cuz I was so focused on this zero issue that I forgot to return a value in the good case. And immediately I got feedback, right? This course sells itself, right? And now we will return null if it passes.
[00:12:30]
And the cool part is, now we're getting complicated enough where we could think about, how would we refactor this? Here I'm doing the math, and if it's infinity, return null. But I could also say, if b equals equals zero, return null, and then forget all that I was doing before.
[00:12:54]
And does this refactor still make everything work? It does, and I have that confidence that everything works.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops