0.3.0 • Published 7 years ago

mltap v0.3.0

Weekly downloads
3
License
Apache-2.0
Repository
github
Last release
7 years ago

mltap Build Status

mltap is a unit testing framework for MarkLogic. It includes a test harness for running tests in Server-Side JavaScript in MarkLogic, an assertion library, and a Node.js-based command-line wrapper.

mltap (partially) implements the tape API, a popular Node.js test framework. This allows you to run the same tests in Node.js, modern browsers, and MarkLogic with no modifications to the test code.

mltap produces standard TAP output so you can use it in other tools that can consume TAP, for example, for continuous integration, IDE integration, or reporting.

Getting Started

First, install the libraries and the command-line interface,

git clone https://github.com/jmakeig/mltap.git && cd mltap
npm install
npm run setup
npm test
npm install --global . # optional

This installs the the command-line interface on your $PATH and configures MarkLogic with the necessary library modules and security settings. You’ll only need to do this once.

Then from within the project you’d like to test,

mltap test/*.test.sjs

Behind the scenes, mltap will run each of local the *.test.sjs modules against the target MarkLogic JavaScript environemnt. mltap collates the results and produces a summary of the passed and failed tests in TAP format to stdout. You can use any TAP consumer to further process the output. For example, tap-diff pretty prints TAP on the command-line.

npm install -g tap-diff
mltap test/*.test.sjs | tap-diff

Example Test and TAP Output

'use strict';

const test = isMarkLogic() ? 
               require('/mltap/test') : 
               require('tape');

test('Throws an error after some assertions pass', (assert) => {
  assert.true(true, 'true is true');
  throw new Error('Test error');
  assert.true(!false, 'not false is also true');
  assert.end();
});

test('This test has a fulfilled plan', (assert) => {
  assert.plan(2);
  assert.true('asdf'.length === 4,  'asdf is length 4');
  assert.true('asdfs'.length === 5, 'asdfs is length 5');
});

test('This test has an unfulfilled plan', (assert) => {
  assert.plan(25);
  assert.true('asdf'.length === 4,  'asdf is length 4');
  assert.true('asdfs'.length === 5, 'asdfs is length 5');
});


function isMarkLogic() {try {return xdmp && cts;} catch(e) {return false;}}
TAP version 13
# Throws an error after some assertions pass
ok 1 true is true
not ok 2 Error: Test error
  ---
    operator: error
    actual: undefined
    at: Test.impl (/test/test.test.sjs:9:9)
    stack: |-
      Error: Test error
          at Test.impl (/test/test.test.sjs:9:9)
          at Test.run (/mltap/test.js:76:12)
          at Object.run (/mltap/test.js:49:28)
  ...
# This test has a fulfilled plan
ok 3 asdf is length 4
ok 4 asdfs is length 5
# This test has an unfulfilled plan
ok 5 asdf is length 4
ok 6 asdfs is length 5
not ok 7 Planned for 25 assertions, got 2
  ---
    operator: ok
    expected: 25
    actual: 2
    at: Test.run (/mltap/test.js:81:10)
  ...

1..7

Development Set-Up

git clone https://github.com/jmakeig/mltap.git && cd mltap
npm install
# Copies the MarkLogic library modules to $ML_HOME/Modules/mltap
# You’ll need to run this anytime the MarkLogic modules change
# This should theoretically work with a modules database in the future
npm config  # Requires MarkLogic running (defaults to admin:admin@localhost:8000)
npm test

For VSCode

Install Node.js TypeScript types to enable code completion,

npm install -g typings
typings install dt~node --global

Set up a task to run tests via npm. The most important part is that the command return the TAP output unaldulterated, i.e. not reformatted or rewritten, as most console pretty printers will do. Anything that you pipe the TAP output into, such as tap-notify, must be a transparent pass-through. The problemMatcher below relies on the specific error reporting format of mltap, which isn’s wholly standardized in TAP.

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "0.1.0",
  "command": "npm",
  "isShellCommand": true,
  "showOutput": "silent",
  "suppressTaskName": true,
  "tasks": [
    {
      "taskName": "test",
      "args": [
        "run",
        "test"
      ],
      "problemMatcher": {
        "owner": "javascript",
        "fileLocation": [
          "relative",
          "${workspaceRoot}"
        ],
        "pattern": {
          "regexp": "^\\s+at: (.+) \\((.+):(\\d+):(\\d+)\\)",
          "file": 2,
          "line": 3,
          "column": 4,
          "message": 1
        }
      }
    }
  ]
}