How it works. You put development-only code into comments and start those comments with tags that indicate what the code is for. For example:
function Account(password) {
// private function
function isValid(pwd) {
return pwd === password
}
/*testable this.isValid = isValid; */
}
Here, testable is a tag indicating that the following JavaScript code makes private code testable. After the tag, the actual development-only JavaScript code starts. It makes isValid() available as a public method. After you have run the development version of the above code, a unit test can work with new Account().isValid().
Development time. You use JSDev to produce the development-time variant of the code. Quoting Crockford:
You give it a list of the tags you want activated. It reads stdin, looking for those tags, and produces on stdout the activated development-mode program.In the above case, you would execute the following Unix command:
cat src/account.js | JSDev testable > srcdev/account.js
Deployment time. Any minification you apply to the code will remove the JSDev comments and thus prevent that the development-only code wastes space.
Other uses. Obviously this technique has other uses, for any kind of development-only code: logging, performance tracking, etc.
3 comments:
I somehow don't favor that approach.
I think public API is fully sufficient to test our code with 100% coverage (otherwise we deal with dead code isn't it ?) also internal logic is not that important as corner input->output cases.
I guess it's what TDD is about, first tests (public API as we wish it to be), then code.
Seems unnecessarily complicated to me. When I've needed to access private functions during development I just expose a method called "test" that evals its parameter, letting you access whatever you want.
In practice, though, isn't testing private functions kinda not the point of unit testing? That is, you're supposed to be able to change the implementation whenever you want without breaking your tests. If the internal code is intended to be general purpose, then I would implement it as another module.
Interesting inkling.
Post a Comment