On Sat, Jun 14, 2008 at 7:00 PM, Brian Eaton <[EMAIL PROTECTED]> wrote:
> I'm writing unit tests for io.js, because I'm about to change it and > changing code without unit tests makes me nervous. Some of the > internal functions are difficult to test because they are hidden in a > closure. I like hiding implementation details in a closure, but I > like testing more. I'm thinking about modifying the code so the style > is more in the style of js classes, such as person.js. > > As an example of the kind of function that is giving me trouble, > consider processResponse. It's had bugs in the past, it will in the > future, but the interface is clean enough that it *should* be > testable. I can't figure out how to test it without pulling it out of > the closure. > > Are there better alternatives? Test the public interfaces. For gadgets.io, you just need to mock out window.XmlHttpRequest and you're good to go. If you've written what you think are adequate tests for all the public interfaces, but there is internal code that hasn't been properly exercised, this tells you one of two things: 1. You have useless code internally. Eliminate it. 2. Your tests aren't thorough enough. Consider what's important here. Does it matter if processResponse (and unimportant implementation detail) changes, or that makeRequest handles all calls correctly? Thorough tests on makeRequest (and the other public methods) will guarantee that the code does the right thing regardless of what changes internally. That's really the core of good testing practice in the first place -- you want to make sure that your code does what it's supposed to do, regardless of what you change internally. What happens if I go through and rewrite large parts of gadgets.io and completely eliminate the call to processResponse tomorrow? I may have introduced new bugs in makeRequest without knowing it. I've violated the public contract, but the tests continue to pass. That's wrong, and the source of most regression bugs in large code bases. To take this further, look a closely related piece of code -- the server-side ProxyHandler. If all we did was test at the HttpFetcher level, subsequent replacements of HttpFetcher with a completely different mechanism for content retrieval could be completely wrong, and we'd never know it because we didn't actually test that ProxyHandler did what it claimed to do. We could have as thorough tests as possible around HttpFetcher (and we should, because it is also a public interface), but that would mean jack squat if we didn't thoroughly test what ProxyHandler was doing, because HttpFetcher might simply change in the future and no longer do this thing that we were counting on. > > Cheers, > Brian >

