2

This is something I often struggle with in testing, yet can never find a canonical or reasonable answer to.


Simple scenario

A function, f(), takes a file, processes it, and returns the processed file. f() has unit tests to check that it performs as expected.

A command-line interface application (CLI) takes a file path as input and uses f() to process the corresponding file.


How should I test the CLI? Passing it a path and ensuring that it handles that path — whether or not the file exists — is logical, but then passing that file to f() and checking the output is exactly what I'm doing in the unit tests for f(). It is redundant and twice as much work. Further, maintaining the tests when the function changes is twice as much work again.

Note: f() can be anywhere — in a library that someone else has written, for example, or part of the whole program itself. I'm trying to understand best practices in (not) redundantly testing functionality, not just in this small example.

1

2 Answers 2

6

Assuming the CLI is a wrapper that parses the command-line arguments, and passes them to f() and does something with the results, the unit test for the CLI would be that it properly parses the command-line arguments and marshals the function arguments for f(), and that the results are properly 'used' (however that is defined).

If f() does file system or network access, you'd probably want to mock / put in a test stub for f() that verifies the arguments are as expected, that it provides given return values from f().

One benefit of modules / decomposition is that you defer to the module responsibility for meeting its contract. It is your responsibility to wisely choose modules. That the module / function you are deferring to has unit tests is a point in favor of trusting and using it, though, I'd really want to see that the tests are actually GOOD tests. :)

1
  • Absolutely. If you need to test X, but X mainly calls f() and f does much more work than X and already has a unit test, then injecting a mock f is the obvious solution. Always avoid duplication unless it's less work than the avoiding would be. Aug 6, 2014 at 14:28
1

How should I test the CLI?

In general, I leave testing the user interface to the user or some stand-in/advocate for the user (QA people). If there are utility functions to say... parse command line arguments, then I would unit test those.

If the wrapping function is not a user interface, then it probably should take f() as a parameter/strategy. At that point, it's trivial to test that the wrapper calls f(), without actually re-testing f(). For a user interface though, I think that is overkill.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.