Examples - uhop/tape-six GitHub Wiki

Simple workflow

Let's assume that we work with a single test file (we'll use TypeScript in this example):

// import test from 'tape-six';
import test from '../../index.js';

test('demo', t => {
  const a = 1, b = 2, c = 'three';
  t.ok(a === 1, 'should pass');
  t.equal(a * b, 3); // error
  t.deepEqual([a, b, c], [1, 2, t.any]);
  eval(t.OK('a + b + c === 6')); // error
});

The test has four assertions. The first assertion is a simple truth check, the second assertion checks if the product of two numbers is equal to some constant, the third assertion checks if an array is equal to another array with a wildcard value, and the fourth assertion evaluates an expression.

The latter assertion shows a convenience method for evaluating expressions:

  • It uses its expression as a message, so we know what we are testing.
  • In the case of failure, it lists the values of all variables used in the expression so we can work out what went wrong.
  • Don't be afraid of eval() — it is not a production code that we ship, it is just a useful tool for testing, which improves the DX greatly ⇒ it improves the quality of our code.

The test has two mistakes.

(Usually we run a test suite and work with individual test files when they show errors. See Set-up tests to learn how to set up a suite of tests.)

Let's run it directly:

Demo - step 1

Obviously, it fails and we need to fix it. In real life we may have hundreds or thousands of tests and their output could be overwhelming. Let's concentrate on the first error and hide all successful tests:

Demo - step 2

We can see that the error is in the second assertion on line 7. Let's fix it:

// import test from 'tape-six';
import test from '../../index.js';

test('demo', t => {
  const a = 1, b = 2, c = 'three';
  t.ok(a === 1, 'should pass');
- t.equal(a * b, 3); // error
+ t.equal(a * b, 2);
  t.deepEqual([a, b, c], [1, 2, t.any]);
  eval(t.OK('a + b + c === 6')); // error
});

Let's run it again:

Demo - step 3

Now our stack trace shows that there is a problem on line 9. What could be the problem? Let's print out the value of expression so we can inspect it:

// import test from 'tape-six';
import test from '../../index.js';

test('demo', t => {
  const a = 1, b = 2, c = 'three';
  t.ok(a === 1, 'should pass');
  t.equal(a * b, 2);
  t.deepEqual([a, b, c], [1, 2, t.any]);
+ console.error('Actual result:', a + b + c);
  eval(t.OK('a + b + c === 6')); // error
});

The result:

Demo - step 4

Now we can see that the actual result is 3three instead of 6. The problem is that we are trying to add a number and a string. Let's fix it:

// import test from 'tape-six';
import test from '../../index.js';

test('demo', t => {
- const a = 1, b = 2, c = 'three';
+ const a = 1, b = 2, c = 3;
  t.ok(a === 1, 'should pass');
  t.equal(a * b, 2);
  t.deepEqual([a, b, c], [1, 2, t.any]);
- console.error('Actual result:', a + b + c);
  eval(t.OK('a + b + Number(c) === 6')); // error
});

Let's run it again:

Demo - step 5

Now our test passes!

Things of note

We don't have any build steps. All tests are run directly. There is no special "test environment". No test runner is required. Nothing obfuscates the code.

We can use a test runner (like tape6) only if we want to run a suite of tests. In this case, the test runner can run our tests in parallel to save us time. And it will run our test files directly.

The other case for a test runner is when we want to run tests in a special environment with some convenience features. For example, we can use a test runner to run tests in a browser environment. See Environment: browsers for more details.

If we start a bundled test server tape6-server and navigate to http://localhost:3000/web-app/?q=/tests/manual/test-demo.js we'll get it running in a browser:

Demo - browser 1

(Note that we renamed the file to test-demo.js because unlike Node, Bun and Deno, browsers cannot run TypeScript directly. But our test file can be run as JavaScript because it doesn't include any TypeScript-specific features like explicit types.)