UNB/ CS/ David Bremner/ teaching/ cs2613/ labs/ Lab 8

Before the Lab


Getting started

Node test runner

Time
10 Minutes
Activity
Demo

In order to provide similar functionality to check-expect in racket, we will use the nodejs test framework.

In order to use the test runner, we need to add two lines to the beginning of our javascript files.

const test=require("node:test");
const assert=require("assert");

We'll talk more about both const and require later.

A test is considered to pass if it does not throw an exception. assert provides several functions useful for this kind of test. We will concentrate on assert.strictEqual for now, which corresponds to the === test discussed in L07.

Here is a complete example with one passing test and one failing one

const test=require("node:test");
const assert=require("assert");

function add1(n) {
    return n+1;
}

test('one plus one is two', (t)=>assert.strictEqual(add1(1),2));
test('one plus one is three', (t)=>assert.strictEqual(add1(1),3));

Test coverage

We will use an experimental feature of node v20 in order to make sure we have test coverage (analogous to how we set up DrRacket for visual test coverage).

Getting a coverage report

Time
15 minutes
Activity
Group activity
ℹ start of coverage report
ℹ ---------------------------------------------------------
ℹ file      | line % | branch % | funcs % | uncovered lin…
ℹ ---------------------------------------------------------
ℹ sample.js | 100.00 |   100.00 |  100.00 |
ℹ ---------------------------------------------------------
ℹ all files | 100.00 |   100.00 |  100.00 |
ℹ ---------------------------------------------------------
ℹ end of coverage report

Writing tests

Time
25 minutes
Activity
Individual

Deep Comparison

Time
40 minutes
Activity
Exercise from book

Follow the Deep Comparison Exercise to write a function deepEqual that passes the following tests. assert uses something very similar for the deepStrictEqual test used below. Your function should pass the following tests.

let obj = {here: {is: "an"}, object: 2};
test("self", (t)=> assert.strictEqual(deepEqual(obj,obj),true));
test("null", (t)=> assert.strictEqual(deepEqual(null,null),true));
test("!null", (t)=> assert.strictEqual(deepEqual(null,obj),false));
test("different", (t)=>
    assert.strictEqual(deepEqual(obj, {here: 1, object: 2}),false));
test("equivalent", (t)=>
    assert.strictEqual(deepEqual(obj, {here: {is: "an"}, object: 2}),true));

Remember from above that you need the following lines to use the test framework

const test=require("node:test");
const assert=require("assert");

It can be frustrating trying to achieve full branch coverage (with our current tools). One useful trick is to turn one sided ifs into two sided ones, so the missing branch is turned into a missing line.

Before the next lab