On Testing (My Sanity)

Mick Annese
6 min readDec 9, 2020

Imagine yourself pacing around your kitchen on a quiet Sunday afternoon: The rays of of the sun lazily pouring through the panes of your windows, a lingering scent of coffee still fills the air from earlier just that morning. The TV is playing your favorite episodes of The Office, but only to produce background noise, as you are here for a very important task. On the table there is opened sleeve of wheat bread, a jar of peanut butter, a glass container filled with jam, a knife, a plate, some paper towels. The next steps are clear and obvious to you. Based on what you have brought to the table, you are going to build a peanut butter and jam sandwich. Delicious. You get started on the process of building such a sandwich in a regular fashion.

  • Take two pieces of bread out of the sleeve and put them onto the plate
  • Use the knife to get some of the peanut butter out of the jar and spread it onto one of the pieces of bread
  • Do the same with the jam on the other piece of bread

Simple! You have successfully built a peanut butter and jam sandwich. While you are taking your first bites you remember that your roommate should be home in about 45 minutes. The idea comes to light: You would have a better chance of getting out of doing the dishes if you made a sandwich that would be ready in the fridge as soon as he walked in the door. Perfect… now to get started…

  • First things first! You take out some bread and get them set up on the plate
  • Next you take the knife and spread some peanut butter onto the first slice
  • Finally, you do the same with the jam and complete the process by putting the pieces together

Easy! now to just put this into the fridge and…WAIT. You notice something different on the corner of the top piece of bread. is that MOLD? You glance to the kitchen counter across the room and notice a fresh pack of bread that you very distinctly remember picking up yesterday at the grocery store. Did you just eat a moldy sandwich? You’re sure you would’ve noticed, but you definitely can’t serve a moldy sandwich to your roommate. So you throw it in the trash along with that sleeve of bread and take out two pieces from the fresh bread on the table. Quickly, you get started making a new sandwich…

  • You spread some peanut butter onto the first slice
  • Masterfully, you do the same with the jam

You have officially outdone yourself. This may be even better looking than the first one that you made for yourself, and it has significantly less mold than the second one. Now all you have to do is put it into the fridge and… WAIT. In the very moment that you remember about your roommates peanut allergy, your roommate walks through the door. You find yourself eating the second sandwich over some light conversation, and very soon find yourself doing the dishes that remained in the sink.

When we are coding it is imperative that we consider the expectation of output before we start building out our solution. In many cases, it is very easy to understand our inputs for simple problems such as building peanut butter and jam sandwiches or daily toy problems. But, in the case of daily toy problems, you may find yourself resubmitting answers several times because you forgot to solve for edge cases. Consider the following object:

var PBJ = function(pb, jam, breadAge) {
this.pb = pb;
this.jam = jam;
this.breadAge = breadAge;
}
PBJ.prototype.isMoldy = function () {
if (this.breadAge > 7) {
return true;
} else {
return false;
}
}

Obviously, with the luxury of time, we could set up a mocha-chai test suite with describe functions such as:

describe(‘PBJ’, function () {  it(‘Should not be moldy if it is made with fresh bread’, function () {  var Sandwich = new PBJ("Gif Peanut Butter", "Smackers Jam", 3);  expect(Sandwich.isMoldy()).to.equal(false);  });});

But in a lot of cases we do not have the ability to test against a full page testing suite in the case of an interview or running multiple toy problems at once. For these cases we must considering the expected output from multiple perspectives. a few Important edge cases that I have found in fighting with tests have been as follows:

What is the expected data type and properties of the output?

In the case of our sandwich above, we can tell that the expected output is an object that takes in a few different parameters. It also shows that there must be a property that takes in the bread ingredient and determines whether the sandwich is moldy. This would indicate also that the property isMoldy would need to be a boolean.

If we did not have access to a mocha-chai suite, we could run this testing natively in our browser debugger or in the IDE by building a test object and passing inputs that we know should produce and expected result into it. in this case, simple testing for isMoldy may look something like this:

var s = new PBJ("Gif Peanut Butter", "Smackers Jam", 3);
s.isMoldy()

The point is, no matter how quick and dirty it is, you need to test that your object actually works.

What happens if a parameter is not passed into the function?

This one is a cause for a lot of simple test failures. What would happen to this object if an age wasn’t passed into the object upon instantiation? Simple, it would error out because it wouldn’t be able to set this.breadAge, and isMoldy would never be able to run. This can be solved for using a simple ES6 default designation

var PBJ = function(pb, jam, breadAge = 0) {
this.pb = pb;
this.jam = jam;
this.breadAge = breadAge;
}
PBJ.prototype.ismoldy = function () {
if (this.breadAge > 7) {
return true;
} else {
return false;
}
}

Ensure that your input and output meets expectations of format.

Failing a test because of format is maybe one of the most bothersome things you can come across. You may feel like this is a trivial and silly reason to fail, but this becomes very real as soon as you are working with databases, APIs, libraries, really anything where your code goes somewhere other than your machine. In this example, spot the reason why my code would fail a test:

var PBJ = function(pb, jam, breadAge) {
this.pb = pb;
this.jam = jam;
this.breadAge = breadAge;
}
PBJ.prototype.ismoldy = function () {
if (this.breadAge > 7) {
return true;
} else {
return false;
}
}

How annoying! Now we will never be able to know if the sandwich is moldy because I cant call isMoldy as I would expect. I may never eat sandwiches again if I couldn’t make this distinction.

Obviously, there are hundreds of things that you could test for before delivering code. In any test driven environment where you are working on ongoing development, you will have to constantly consider the outputs and inputs from and to your system on a daily basis. It is important to consider these things and also how edge cases may behave, even on simple toy problems. Switching to a testing driven mindset as the foundation for your code will make any problem solvable, because you are just starting with typing. One of the biggest problems that a lot of coders have, myself especially, is rushing to provide a solution. You may feel like this is a good thing, as shows that you are capable of timely delivery of code. But, if you consistently put out code that fails the expectations of those who request it, it may prove difficult to gain the trust of a potential employer… or you may end up in a future of infinite debugging rabbit holes. Either way, it is important to write your code with testing in mind, just like it is important not to serve peanuts to unsuspecting allergic roommates, as both of these things will lead to you doing dishes in the end of it all.

--

--