Skip to content

Instantly share code, notes, and snippets.

@BrianLitwin
Created August 15, 2019 13:39
Show Gist options
  • Save BrianLitwin/5d074710dcd6e447aef19627227f1000 to your computer and use it in GitHub Desktop.
Save BrianLitwin/5d074710dcd6e447aef19627227f1000 to your computer and use it in GitHub Desktop.

The way in which you’ve structured makeExporGraph is a wonderful example of how taking data dependencies rather than directly depending on global values can make your code easily testable in a natural way that does not require writing any mocks.

You are testing a pure function that operates on two interfaces: the IAnalysisAdapter interface and the Stdio interface. At test time, you provide a Stdio implementation that captures its output into memory, and an IAnalysisAdapter implementation that has some fixed success or failure behavior. At runtime, the Stdio interface is connected to the actual file descriptors, and the IAnalysisAdapters invoke useful plugin code. Crucially, because the function created inside of makeExportGraph only knows about the interfaces, the fact that it is correct on sufficiently exhaustive tests of the “stub” implementations means that it is also correct on the “real” plugin code.

If makeExportGraph had directly used console.log/console.error and looked up a global list of adapters, then we could attempt to write tests for it by mocking out those values. But this is brittle: you’d have to remember console.warn and console.debug, too, for instance, and if we move the global list from common.js to defaultPlugins.js or something then you’d have to update all the mocks. Instead, by programming against the specifications rather than the implementations, you’ve managed to write robust, comprehensive tests without much overhead in the test code.

Modules matter most.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment