Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command not unit test friendly #438

Closed
phdunham opened this issue Sep 25, 2015 · 13 comments
Closed

Command not unit test friendly #438

phdunham opened this issue Sep 25, 2015 · 13 comments

Comments

@phdunham
Copy link

I a lot of unit tests for my code to test parsing the command line. Commander instantiates on the require('command') statement and is cached. My unit tests do not have a way to reset commander back to its initial state. Many of my unit tests fail because values from the previous unit tests inside of commander carry over.

can we get a way to create a new Commander() each time for unit testing. Or at least a function like commander.reset() to flush the previous state of commander between unit tests?
Thanks

@tandrewnichols
Copy link
Contributor

You can use proxyquire to control it, or . . . if you don't like stubs (depends on your school of thought for tdd), use clear-require to reset the state of the module and then require it again.

@lukeasrodgers
Copy link

@phdunham you could try the approach in my PR #499, or follow the approach taken by commander.js itself, i.e. each test in a separate file.

@skratchdot
Copy link

It would be nice to have the library stop using globals, and allow things like "log" and "error" to be passed as options. Also consistent usage of console.log vs process.stdout.write (always using console.log seems like the way to go).

I've had a pretty miserable time trying to unit test my cli w/ code coverage. I ended up needing to use spawn() to write my tests (which works okay), but I haven't gotten coverage w/ istanbul working yet. When I tried using sinon to override things like process.exit, and process.stdout.write, I entered the rabbit hole.

Started working on a PR here to allow all globals to be passed as params, but that didn't seem like it would actually help in the end. Hopefully someone here can post some links to successful cli unit testing with code coverage! I know I'd be interested in other examples (my approach isn't the best- and other examples I've tried never work in my codebase)...

@nene
Copy link

nene commented Jan 21, 2017

Turns out that the solution already exists. The Command class can easily be imported and instantiated:

import {Command} from "commander";

const commander = new Command();
// now use the local instance as you would use the global one...

It simply doesn't seem to be documented anywhere besides the code itself.

I ran into this problem once again when I was upgrading to Mocha 3.x. Suddenly all my tests against commander started to fail as Mocha was also using the global commander instance and the command line options my library was using got mixed together with command line options of Mocha. Rewriting my CLI to instantiate separate Command class solved the whole problem easily.

@roman-vanesyan
Copy link
Collaborator

You can use new commander.Command() to instantiate a new Commander instance. Close for now.

@akataz
Copy link

akataz commented Jun 28, 2017

@vanesyan thanks for that i've been puzzled for a while! Worked like a charm.

@ChristofferSkog21st
Copy link

Are there any unit testing examples? Haven't been able to find any.

@shadowspawn
Copy link
Collaborator

There are the unit tests for Commander itself. Most of them predate the "new commander.Command" style but these two got updated recently.

@ChristofferSkog21st
Copy link

@shadowspawn Yeah saw those, thanks. I can't find any way of testing commands that have prompts in them though, is that even possible?

@shadowspawn
Copy link
Collaborator

What prompts? I have seen Commander did once support prompts (e.g. #163) but not since I started using it, so that might be another library.

@ChristofferSkog21st
Copy link

I'm using this https://www.npmjs.com/package/prompt to prompt for login details for the database for example. So the flow would be:

  • Run command
  • Fill in username + password
  • Check result

Step 1 and 3 are simple enough but the prompt bit I'm unsure of how to achieve.

@shadowspawn
Copy link
Collaborator

Sounds like a question for Prompt rather than Commander! But as a suggestion, you could read the login details from environment variables for testing purposes to avoid the interactive prompt.

@ChristofferSkog21st
Copy link

Hmm not a half bad idea that. Would require some code tweaks but should be easy enough, thanks :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants