Adding tests to video player code

Testing the code inside jsitor with autoplay turned on, each of the correct videos play.

All this is able to say, or confirm is that the videos work.

No error messages appear in there either.

Is any progress able to be made from here?

Are there steps that can be done to get it working?

We have found ourselves at a place where tests are needed, to figure out what is behaving as expected and more importantly what is not behaving as expected.

Until you agree to use tests, it will remain broken.

We can do tests.

Working code: https://jsfiddle.net/24xf0avp/

Broken code: https://jsfiddle.net/kxhyLdr8/

Tests are about twice as hard to create after having made the code.

The normal process is that you want the code to do something different, so you write a test about what you expect to occur. Then you write the code to achieve that thing, and the test confirms that you did it properly.

It’s like when getting in a contractor to work on your house. There is a quotation for the job (that’s the test), the work is done, and afterwards the work that was done by the contractor should match up with what was on the quotation.

There are several different types of tests, ranging from:

  • acceptance tests, does it do what the customer wants
  • system tests, all modules including network and database
  • integration tests, communication between different modules
  • unit tests, where individual module methods are tested

Usually the number of tests form the shape of a triangle, with very few acceptance tests, and the most tests being unit tests.

At its most basic, we can figure out what unit tests are needed by looking at the return object at the end of a module. Those are the things that need testing.

There is a testing framework called Jasmine, that can be used with jsfiddle to do testing. http://jsfiddle.net/jasonmcaffee/yhZBv/

We can start by putting together tests for the working code.

The module methods that need testing are:

  • manageCover.addCoverHandler
  • manageCover.init
  • manageUI.addExitHandlers
  • manageUI.getWrapper
  • manageUI.init
  • videoPlayer.addPlayer
  • managePlayer.adder
  • managePlayer.removePlayerHandler
  • players.add
  • players.init

I recommend that the code at http://jsfiddle.net/jasonmcaffee/yhZBv/ is forked, on to which things are added one at a time as each of those module methods are tested.

1 Like

Will this be more difficult since there are no errors in console?

Usually errors are the gateway to finding a solution to fix whatever that is not working how it should.

In the code, do we force an error to occur or something like that?

With tests, we can expect a different outcome to check that the test shows a suitable error.

What makes things more difficult is that some of the code will be hard to test, because it wasn’t written with tests in mind. I have attempted to remedy some of that in the work I’ve been doing.

Nothing gets around a fundamental fact of life though that writing tests beforehand is light and breezy experience, and writing tests afterwards is a gruelling grind.

2 Likes

Was I given instruction to do something?

Okay, to get started we will create some tests for the manageCover() module in the code at https://jsfiddle.net/24xf0avp/

Create a fork of the Jasmine test page at http://jsfiddle.net/jasonmcaffee/yhZBv/
I think that it makes sense to have a separate forked page for each module that we test.

In that forked page, paste a copy of the HTML and CSS code from https://jsfiddle.net/24xf0avp/ into the forked page.

Then also copy the manageCover() module across into the forked page too. Place the module right at the top of the Javascript code.

When you’ve done that, we should be ready for you to write your first test.

1 Like

I’m confused,

Why are we testing the working code and not the broken code?

How do we find out what is not working in the broken code if we are testing a code that is already working?

Working code: https://jsfiddle.net/24xf0avp/

Broken code: https://jsfiddle.net/kxhyLdr8/

I did what you asked me to do here: https://jsfiddle.net/yvpmwe69/

Why aren’t we testing the bad code right now? We don’t know enough about the bad code right now to understand what is good and bad. End result, our tests on the bad code are likely to show that some bad things are good, which is not what we need.

Instead, we are testing the working code because starting from a good and reliable code is better. When tests are in place for the manageCover code we can then try them on the non working code.

At the end of the CSS code, hide the outer class. We don’t want to see the player buttons. On this page it’s the tests that are important for us to see instead.

.outer {
  display: none;
}
1 Like

I did what you asked here: https://jsfiddle.net/c4exLzaq/

We do know this.

After clicking on a button.

How console log should look.

Working code: https://jsfiddle.net/24xf0avp/

Broken code. https://jsfiddle.net/kxhyLdr8/

fadeInExit along with the curtains opening don’t seem to be working in the broken code.

Good one. Let’s start nice and easy by testing the first function in the manageCover module. The end of manageCover has two methods, one is addCoverHandler and the other is init.

Near the end of the code modify the describe block, so that instead of saying running jasmine in jsfiddle it says init. We are going to test the init part of the manageCover module.

We can’t see where it says init all that well because of the background color. Please update the background color so that we can more easily see the text. I recommend adding to the end of the CSS something like floralwhite , as it’s not quite so harsh on the eyes as white.

body {
  background: floralwhite;
}

On the next line, the line that starts with it, rename it to with no parameters. There is a better name to use for that, but that’s only after we have a better understanding of that situation.

Fail => Pass => Refactor is the testing cycle. Because the code has already been written, this will mostly be Fail => Pass without the refactor, but it’s useful to keep in mind.

Right now we are writing a test to make something fail. After which we make it pass. But first, the fail.

Below the it line, replace what’s there with a call to the init method of manageCover, using no function parameters. You should then see a suitable failing test, which is the first part of the testing cycle.

We should always start with no function parameters, and after tests pass we add on more things from there.

1 Like

I am seeing a failing test: https://jsfiddle.net/rhacdnu6/

describe("init", function(){
    it("with no parameters", function(){
    manageCover();
    });
});

Yes you are seeing an error, but its not the error that we want or expect. The error message says:
TypeError: manageCover is not a function

It’s completely correct about that, because you didn’t seem to understand some of the instructions.

You have made a call to the manageCover object, but that is illegal because the manageCover object is not a function.

Your instructions were not to make a call to manageCover. Instead, they are to make a call to the init method of manageCover, with no function parameters too of course.

After doing this it says it passes, but we want it to fail.

https://jsfiddle.net/af56pvuz/

describe("init", function(){
    it("with no parameters", function(){
    manageCover.init({});
    });
});

Then give it no function parameters. You have been asked to not give it function parameters two times already This is the third time.

Like this? https://jsfiddle.net/af56pvuz/1/

describe("init", function(){
    it("with no parameters", function(){
  manageCover.init();
    });
});

Good one. With no parameters it is expected that an error occurs, because a selectors are used to get the container and play button. We can tell the test that we expect that error to occur, by replacing the line with expect(…).toThrow().

expect(() => manageCover.init()).toThrow();

For greater clarity, we can extract that function call out to a separate fnCall function.

const fnCall = () => manageCover.init();
expect(fnCall).toThrow();

Now that we have specified that no parameters is expected to throw, we have the opportunity to provide a better error message by updating the test to indicate the message that we want, so that we can update the code to provide that better error message.

However, we are more interested in just getting some basic tests out. So after the test with no parameters is passing, we can move on to a test where we give it some parameters.