Rob Johansen
Rob Johansen

Reputation: 5164

How to unit test a tool that uses command-line-args

I'm using mocha to write unit tests for a tool that uses the command-line-args npm module. Unfortunately, the options intended for mocha are picked up by command-line-args in my tool, which dutifully throws an error if those options don't exist in my tool. For example, if I do this...

mocha --watch

...then command-line-args throws this:

UNKNOWN_OPTION: Unknown option: --watch

I can work around the problem by doing something like this in my tool...

var cli = commandLineArgs([
    { name: 'verbose', alias: 'v', type: Boolean },
    { name: 'timeout', alias: 't', type: Number },
    { name: 'watch'} // So I can do mocha --watch
]);

...but then cli.getUsage() says my tool has a watch option that it doesn't really have. And of course this gets out of hand if I want to pass more options to mocha.

What's the best way to "tell" command-line-args to ignore options in my scenario?

Upvotes: 17

Views: 7083

Answers (3)

Lloyd
Lloyd

Reputation: 8406

What's the best way to "tell" command-line-args to ignore options in my scenario?

By setting either the partial or stopAtFirstUnknown flags in the commandLineArgs options. Example usage in a mocha script here. Full docs here.

Upvotes: 1

Ateş Göral
Ateş Göral

Reputation: 140050

You should break your tool into a core part that takes in a configuration object and a command-line wrapper that uses that core part. Then you just unit test the core part.

Your aim really should be to test the core part, which is the part you've written; and not to exercise/test the command-line-args module, which in theory you should trust as being already proven to be working by its author.

Upvotes: 18

Peter Lyons
Peter Lyons

Reputation: 146034

I would write the entrypoint code into your CLI app such that it can explicitly take an array of strings as the arguments, only using process.argv directly as a default. Then you can pass in various argument lists for unit testing purposes but still do the right thing when run in production. Pseudocode:

function cliMain(args) {
  args = args || process.argv
  // parse args here and proceed
}

Upvotes: 8

Related Questions