8.2 Initial Test Coverage - Video Tutorials & Practice Problems
Video duration:
10m
Play a video:
<v Instructor>Now it's time to get started</v> with automated tests. Our initial task is to write some tests for the current functionality of our palindrome detector. We'll do that in a standard file called test.js in a test directory. This is part of the way MoCA works. Do mkdir test, and then call it test.js. In order to make our test, we're going to use a node library called 'assert.' The way to include it into our test file, is to use 'require.' We've talked about before how JavaScript doesn't have a native way to require one file into another, but node adds one, like this. We'll be using this assert variable. So we use 'let' to create a binding, require, assert. And then we also have to require the phrase code, including palindrome, which is an index.js, one directory up, which we indicate with dot dot. Now here, the reason that we can just set 'phrase' equal to this 'require' is because of this module.exports phrase. When we require index.js, the result is this object, to find down here, which we then bind to this phrase variable here. Now, when doing this kind of testing, I really like to use two panes, one for the test code, and one for the application code. You can split the panes like this. Now you see we've got the test code on the left and the application code on the right. All right. So how do we test this palindrome function? Well, the assert library includes two important functions. One called 'describe' and another called 'it.' These might sound a little cryptic, but they allow us to make natural sounding tests. Let me show you how that works. We're going to describe phrase, just give it a string as an argument. And then we give it a function as an argument, an anonymous function. And it's a function of zero arguments. So we just do this. Like that. Open curly brace, and then just put it in the semicolon. So we don't forget it. And now in this case, we're going to be describing the palindrome method. There's a standard way of denoting that a method is part of an object, which is to say, it can be called on instances of that object. It's like this. You'd write phrase, hash symbol, palindrome. Like that. The text has already used this notation a few times, but I don't think I've mentioned it yet in the screencast. In any case, because we want to describe phrase, hash, palindrome , what we're going to do is have a nested describe block like this. Also, with an anonymous function of no arguments. Again, this is the kind of thing that you wouldn't necessarily be able to guess. I just pulled this from the documentation. So, there we go. Describe that, put in the semicolon. And now we're ready for the real heart of it. We're going to put 'it,' which is actually a function. It takes in an argument, which is a string describing what we're testing. And let's start by testing a non-palindrome. So we're going to say that 'it' should return false for a non-palindrome. Then, like 'describe,' 'it' takes anonymous function as zero arguments, like that, and then let's put in the semicolon. All right, this is the place where we actually write the test. I'm gonna start with the simplest possible assertion. This doesn't test anything yet, but I just wanna show you what happens. I'm going to say assert, true. Like that. And then run our tests. Because we told NPM that we were using MoCA, that was in the previous section, we can run NPM test, to run the test suite. Oops. And I made a mistake. Maybe you noticed this when I did it. I accidentally did touch test.js, instead of touch test/test.js. So let's move this file in. Put it back up. There we go. Let's try that again. And there we go. You can see that assert true gave us this passing test. Similarly, assert false gives it's a failing test. So, in order to test the palindrome functionality, we can define a non-palindrome like this. To new phrase. We're building up to a palindrome called 'Madam I'm Adam.' So in that theme, sort of a Garden of Eden theme, let's choose 'apple' as our non-palindrome. So, how do we assert that this is not a palindrome? Well, nonPalindrome.palindrome should return false, which means we wanna assert that this is not nonPalindrome.palindrome. Right, so if this is false, then bang that thing, and the negation is true. And we saw that assert true, gives us green, as required. Here we go. Similarly, let's make a test for something that is a palindrome. Should return true for a palindrome. This is just a plain palindrome. It's a word that's literally, letter by letter, the same forwards and backwards. So let's say, return true for a plain palindrome. And your plain palindrome, let's use 'race car,' like that. And then assert that this is a palindrome. By the way, you might see that things are kind of going off to the right here. If you look at the number of columns, it's actually just fine at 67. I generally try to keep my lines under 80, but I'm using a bigger font for screen casting purposes. Normally, I would use a font small enough that it would mostly fit. So, oops. And you can see here that it's indented too much. De-dent it there. And we should be ready to go. Let's run this test. There we go. So what good does this do us. Well, we've written these tests for our palindrome detector. We were already pretty sure that this was working, but recall from our previous work, that we had to keep '.loading' it in the node repl, in order to test it. And that was really cumbersome. This way, if we make a change to our code that breaks it, we can find out right away by running the test suite. So for example, if we got rid of reverse here. Aha. It's red. We must have done something wrong. So having a test suite, lets us make changes more confidently. It's not a proof that the code is right, but it's definitely reassuring. All right, before moving on, I'd like to take a look at where we're going. We're going to add a couple of pending tests for things that we'd like to add. One of them, in fact, is something we already have. And the other is what we'll be working on for the rest of this chapter. So let's start like this. So we start with 'it.' And if, instead of giving it a string and a function as an argument, we give it just a string. Then it creates what's called a pending test. So one of the things we wanna test for is a mixed case, palindrome, something like 'race car' where R is capitalized and C is capitalized. We have this two lowercase over here, that takes care of that, but we don't have a test for it. So we can just do this, and then run the test suite. And you can see that we've got one pending test. Here this is shown in blue. Some systems show it in yellow. It's often called 'yellow' as an intermediate state between passing, which is green, and failing which is red. An analogy with traffic lights. But most of the time, I call any test suite that doesn't have any failing tests, green. In any case, we have a nice indication here of something to do in the future. And in fact, this is left as an exercise, but I'll solve it in the next section. But the second test, this is what we're gonna be working on. This is the real challenge. It should return true for a palindrome with punctuation. It's writing test code for the second test, and then writing application code to get it to pass, that'll occupy our attention the rest of this chapter.