<commit_before>It may seem strange to talk about tests in the context of debugging,
but in reality they're one of the most useful debugging tools you
have. The process of reducing a situation down to something simple
enough to fit in a test case teaches you a lot about the problems your
program is seeing, and once the test is finished (and the underlying
bugs are fixed), you can add it to your test suite as a guard against
future regressions. Also, once you've reduced the issue down to its
simplest manifestation, you've got a jumping-off point to use with a
debugger (about which more will be said later).

Testing is far too large a topic to attempt to cover in depth here.
<NAME>'s "JavaScript Testing Recipes" is an entire (excellent)
book devoted to testing in JavaScript. Similarly, there are even more
test runners than test frameworks for Node, and there's no reasonable
way to single one out as being better than all the others. However,
there are a few things to look for in a test framework when you're
using it as a debugging tool:

  * You should be able to run your test cases directly from the command
    line, without the use of a special-purpose binary. Stepping through
    a bunch of code that has nothing to do with your problem each time
    you run the test is a drag.
  * The test framework can't do anything fancy with events,
    error-handling, or otherwise monkeypatch the runtime. The more
    clever moving parts there are in the test framework, the more likely
    they are to interfere with your application in a way that makes it
    tough to figure out what's wrong with your program.

A good, simple framework that has both these properties (among many
others) is tape. tape produces TAP output, its test suites can be run
directly with node, and it comes with a rich set of assertions -- and
very little else.

Frequently, it's useful to write a set of test cases to exercise all the edge
cases of your program. The following example is contrived, but it shows the
basic pattern. It gets passed a tape test object by the verifier, so you don't
need to call t.end(). Also, it has something wrong with it (it shouldn't be too hard
to figure out):

    module.exports = scenario;

    function scenario(t) {
      t.ok(isGreaterThanZero(Infinity), "1 is greater than 0");
      t.ok(isGreaterThanZero(1), "1 is greater than 0");
      t.notOk(isGreaterThanZero(0), "0 *is* 0, not greater than 0");
      t.notOk(isGreaterThanZero(-0), "why does -0 exist");
      t.notOk(isGreaterThanZero(-1), "-1 is definitely not greater than 0");
      t.notOk(isGreaterThanZero(-Infinity), "1 is greater than 0");

      function isGreaterThanZero(value) { return value >= 0; }
    }<commit_msg>Fixed description in tape assert<commit_after>It may seem strange to talk about tests in the context of debugging,
but in reality they're one of the most useful debugging tools you
have. The process of reducing a situation down to something simple
enough to fit in a test case teaches you a lot about the problems your
program is seeing, and once the test is finished (and the underlying
bugs are fixed), you can add it to your test suite as a guard against
future regressions. Also, once you've reduced the issue down to its
simplest manifestation, you've got a jumping-off point to use with a
debugger (about which more will be said later).

Testing is far too large a topic to attempt to cover in depth here.
<NAME>'s "JavaScript Testing Recipes" is an entire (excellent)
book devoted to testing in JavaScript. Similarly, there are even more
test runners than test frameworks for Node, and there's no reasonable
way to single one out as being better than all the others. However,
there are a few things to look for in a test framework when you're
using it as a debugging tool:

  * You should be able to run your test cases directly from the command
    line, without the use of a special-purpose binary. Stepping through
    a bunch of code that has nothing to do with your problem each time
    you run the test is a drag.
  * The test framework can't do anything fancy with events,
    error-handling, or otherwise monkeypatch the runtime. The more
    clever moving parts there are in the test framework, the more likely
    they are to interfere with your application in a way that makes it
    tough to figure out what's wrong with your program.

A good, simple framework that has both these properties (among many
others) is tape. tape produces TAP output, its test suites can be run
directly with node, and it comes with a rich set of assertions -- and
very little else.

Frequently, it's useful to write a set of test cases to exercise all the edge
cases of your program. The following example is contrived, but it shows the
basic pattern. It gets passed a tape test object by the verifier, so you don't
need to call t.end(). Also, it has something wrong with it (it shouldn't be too hard
to figure out):

    module.exports = scenario;

    function scenario(t) {
      t.ok(isGreaterThanZero(Infinity), "1 is greater than 0");
      t.ok(isGreaterThanZero(1), "1 is greater than 0");
      t.notOk(isGreaterThanZero(0), "0 *is* 0, not greater than 0");
      t.notOk(isGreaterThanZero(-0), "why does -0 exist");
      t.notOk(isGreaterThanZero(-1), "-1 is definitely not greater than 0");
      t.notOk(isGreaterThanZero(-Infinity), "-Infinity is definitely not greater than 0");

      function isGreaterThanZero(value) { return value >= 0; }
    }
{'fraction_non_alphanumeric': 0.05488694383661561, 'fraction_numerical': 0.006017505470459519, 'mean_word_length': 3.828345070422535, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5868507', 'n_tokens_mistral': 1480, 'n_tokens_neox': 1394, 'n_words': 866}