Properly testing solutions in coding interviews is something that I see a lot of people struggle with, but is absolutely critical for getting the job.
Check out this video where I break down why you should test your code and show you exactly how to do it.
Video notes:
Video Transcript
Hey everyone, Sam here from Byte-by-Byte.com. Today I want to talk about testing, but before I do that if any of you guys have yet to go over and check out the blog you should definitely do that. There's a lot of great material on there including blog posts about questions that people have often asked me. There are practice interview questions, and there's a ton of other material. So definitely go over there and check it out.
Now moving on to testing, this is something that I think doesn't get talked about enough. And so I really wanted to talk about this in the context of interviewing. We always focus on getting the right answer all the time but we don't talk about how maybe your answer is not going to be correct right away. And that's okay as long as you go back test your solution and correct it.
So testing is really important for several reasons, one is that a lot of us make really stupid mistakes. We'll do things like accidentally put a single equals instead of a double equals when we're trying to compare two values. Or we'll you know forget a semicolon… they can be little things but those things add up when you're an interviewer watching someone code. It makes you think that, especially if they don't catch them that they're just going to be a sloppy coder and that you're going to constantly be having to correct little issues like that.
Another really common thing that comes up in interviews is that your interviewer will ask you, “is your solution correct?” when you're done coding up your problem. And so there are two possible approaches to this. One is to say I don't know I think it's correct. I mean I like you can sort of stumble over it and not really know. Or you can test your solution and then you know. And then you can have confidence and say, yes I think my solution is correct because I tested it and I saw that it worked in these test cases.
There may still be edge cases and so it's possible that you won't be able to test everything, but you can at least have confidence in your answer that you give to them. The last thing is that this just shows that you're thorough and careful about your work. Which going back to my first point is something that employers really really care about. They want to know that you're going to be someone who they don't have to micromanage on a regular basis and that you're just going to turn out good code.
And so by testing your code and showing that you care, you're really showing them that they're not going to have to worry about you. So now I want to transition into actually how we test the code, because I find that that can be as big of a stumbling point for people as anything else.
The first thing that we want to do is talk through the logic of the code. And this sort of makes sense, and this is what most people do but most people end up leaving it at this step. So you want to talk through the logic and make sure that makes sense. Make sure that what you're doing makes sense and that it's solving the problem that you were asked. You want to make sure that you have the input that is being requested in the problem, and the output that's being requested in the problem.
If someone's asking you to print out the output and you're actually returning a list of strings, then that's clearly a problem. So you want to make sure that you go through the logic carefully. The next thing you want to do is go through your code line by line.
A lot of people stop with a broad overview, but you need to go through line by line to actually see whether there are specifics and tactical errors in your code. And in a minute I'm actually going to go through an example where I'm going to show you how to do this. And show you how you can keep track of what you're doing as you go, because it can be a little confusing to do that. And so you don't actually have to go through every line of the code again and again, so if you have like a for loop or something you don't have to go through your loop 20 times, but you do want to make sure that you test and manually go through at every line of code at least once.
And also if there are any weird edge cases that you test those. So what you can do is basically pick an example of an example input. So for example it could be the codes they gave you. Or if there are common… if there's an edge case that you came across you can test that as well. And then by testing that you will be able to actually go in and make sure that your code is correct.
So now what I want to do is actually go and we are going to look at an example. So here we have an example problem that removes all the duplicates from a linked list. And we want to test it. So let's start by testing it on a high level and just going through the logic of it. So when we we take in a linked list and we create a hashset and then what we're going to do is we're going to have some previous we see some previous node here. And then while N is not null so N was the original list while N is not null we're going to say we're going to check whether our hashset contains the value. And if it contains the value then we're going to say that the previous node now points to the next node.
So we're basically skipping the current node if it's a duplicate, and otherwise we're adding our value to the list, and then we increment N. And then at the very end we're checking whether or we're saying that prev. next is equal to null which would basically mean that the…Which would basically mean in this case that if we have like I duplicate at the end of our list then we're going to set that to point to null. And so now that we've gone through it on the overview and that sort of makes sense, let's go through and we'll actually test it with an example.
So we need a linked list, so let's just pick a linked list for our input. And in this case we also want to think about the edge cases for our input. So I'm going to do a four node list. So that it's not super long and it's not going to take us a super long time to test this. And then we know that we need to have duplicates in our list, because if there are no duplicates we're just not going to do anything. We're just going to keep incrementing until we get to the end. But one edge case that we did up here is what if the very last node is a duplicate, then we want to make sure that the end of the list is pointing to null as it's supposed to. So let's create a list where we're going to have the second node and the last node be duplicates. Just so that we can test both when there's a duplicate in the middle of the array of the list, and duplicate at the very end.
So we'll say one, two, or actually we can say 1 1 1 1 2 2 like this. So that way we have this is a duplicate here and this is also duplicate at the end. So our expected output is going to just be a two node list, which is going to be 1, 2 pointed to null. So now that we have our test input let's go ahead and execute our code manually. So we see that we start we have our input N is going to be I'm just going to refer to this it's going to be this node but I'm going to refer to it by the number the value of the node, which is what I usually do just because it's a little bit easier than trying to keep track of like. And then I'm going to just know that this this variable is represent the node and not the value. And then that's just a little bit easier I find. And so we're going to have we're going to create this empty hashset of integers that we're going to call nodes. So let's add that. It's just going to be an empty hashset. And then we are going to instantiate this prev value to be equal to null. So we're going to have prev equals null. And this I would draw out exactly this on the whiteboard.
I think that it's really easy to try and keep stuff in your head but there's really no reason to because it's so easy to just write stuff out. Or even if you're doing it in a text editor or something you can type this out as well. And just keeping track of all the values makes it so much easier to not get lost in your code.
So now we're going to come to here, we're going to start a while loop or say in this case N is not equal to null. So we're going to come into our loop nodes is our hashset and nodes.contains, n.val, so n.val is 1 in this case, and there's nothing in our nodes set. So we don't so we're going to skip that condition and we're going to come down to here. We're going to say nodes.add n.val. So we're going to add the value to this set here. And the value in this case is going to be 1. Now we save prev=n so prev is going to be equal to this one node as well, and in this case specifically it's the first one node. And then we're going to come down here we're going to say n=n.next. So now N equals 1 again but it's the second one. So let's do like 1 star. So we come back to the top of our loop N is not equal to null, but nodes does contain n.val. So we have prev.next= n.next. And so prev is this node here and prev.next is this pointer and n.next is the 2, so prev.next now points to end.next like this. And so we're going to say we said prev.next = n.next, and now n=n.next. So now n is going to be equal to 2 as well.
And notice that we didn't increment prev in this case. And we don't actually want to increment prev because the previous value for our new linked list with this you know one value this second node removed is still going to be the same previous node as before. So we don't correctly, we don't want to increment our we don't want to say prev=n in this case. And so now we're going to say we're going to come back to our loop, we're going to say does nodes contain n.val, does nodes contain two? No it doesn't.
So we're going to add 2 to our list. For our set and now we're going to say prev=n. So now prev is equal to 2 and n=n.next. So N is now equal to, well I guess we didn't have to erase it. But it's going to be like 2 star. Right it's going to be this second two. So finally we get we come up to our while loop again and N is still not null. Nodes does contain, so prev.next=n.next. And so prev is this and it's this too. So prev.next = n.next which is null. Which is what we want. And then we're going to say n=n.next. So n is equal to null.
And then finally we're going to come back to our loop, we're going to say that while n is not equal null in this case n is null. So we're going to come down to the end and we're going to say prev.next=null. So this is just this would actually help us more I believe if we had multiple duplicates at the end. But it's only going to it's going to basically say that this is pointing to the same place that it was anyway. So it's just going to repeat that and it's not going to have any change, and then we basically these pointers since we never got rid of this pointer from the initial node and from the 2 deleted nodes, but it doesn't really matter.
So our final result is just here I'll do it in a different color. Is just this node which points to this node which points to null. And therefore we have exactly this. And get the right result. So that's all there is to testing it, but testing it properly and testing it in a way that actually really tests is incredibly important. So I highly recommend that you take time to practice this whenever you go through practice problems, or even if you have a practice problem that you've already done, you can go back to it and just test it.
And practice doing it out loud as well because this just reflects so much better on you from the perspective of your interviewer. And so I highly recommend doing this whenever you are doing an interview. So that's all there is about testing, definitely let me know if you have any questions about this or anything else in the comments below. Make sure you come over to the blog if you haven't already because there's a lot of great material over there. And otherwise hope to see you guys again soon.