A quick thought on testing your code in interviews

Testing sucks in interviews because it takes time and feels like a waste if you think you don't have a bug. It also feels like it takes too long if you do have a bug. No matter what you do, you can't win.

Most major tech companies factor in your ability to test your code. Facebook's model of having a "verification" section in their rubric is particularly interesting.

I think of verification happening twice in the interviewing process:

1) Verification happens at the start of the interview, in the form of clarifying questions and verifying that you understand what the question is asking.

2) Then verification happens again at the end of the interview, after you've written the your solution, and you need to verify that it works.

Strategy One - “Integration” tests

An integration test in software engineering is an end-to-end test of the system.

In this case, can simulate an "integration" test by picking a few inputs and running them by hand through our code from end to end, ensuring that we get the expected behavior. If code verification is going to happen in the interview, 90% of the time this is how it is done. It is even recommended in books like Cracking the Coding Interview.

I wouldn’t say that this is “wrong” but it amazes me that this seems to be the only strategy people try.

Strategy Two - “Unit” tests

I was talking with a fellow Googler and friend, Nil Mamano, about this phenomenon. We discussed alternative methods to running through your code and he had the suggestion of “unit tests” for our code. So for example, in a binary search, you can run end-to-end “integration tests” (this is a useful framework for that!) but you can also just focus your attention on the “tricky lines” and practice just with them. Let’s say this is your binary search code:

def binarySearch(arr, target):
  l , r = 0, len(arr) - 1
  while l <= r:            
    mid = l + ((r - l) // 2)
    if arr[mid] == target:
      return mid
    if target > arr[mid]:
      l = mid + 1
    else:
      r = mid - 1
  return -1

Sure, you can run through inputs and try to get it to work, or you can focus on the tricky parts of the code. In this case, the tricky parts are the while loop and what we set our pointers to so we can focus just on those lines and run through examples with them.

while l <= r:

Ok, so focusing just on this line, what are we assuming about the code? According to this conditional we will not stop until the pointers pass one another, with a one-element array being an interesting case here. Let’s think through a couple of inputs and where the pointers could end up…

Two element case:
START
[1, 2]
 l  r

END
[1, 2]
 r  l    


One element case:
START
[1]
 l
 r

END
[1]            OR      [1]
 l                      r
     r               l

This idea of single-line testing is often more efficient than trying every test possibiliity.

Strategy Three - Bravado

If you're confident in your code, often, you're better off displaying that confidence. Running through an input that you know works and then declaring that the function works often is the fastest way to get through this section of the interview. Unless an interviewer has spotted a bug, you're usually fine, and you come off as more confident.

I think this can easily be a mistake if you’re not confident, but more people should be confident in their coding skills.

Previous
Previous

How hard is it to cheat in technical interviews with ChatGPT? We ran an experiment.

Next
Next

Avoiding common binary search mistakes