Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I wonder what testing functionality, specifically, they see missing in the Node ecosystem...


I'm writing a server in Node and to date I'm still trying to figure out how to control the main loop from Node. I want to write tests like this:

    1. register some timers and create some sockets
    2. send some stuff over the sockets
    3. wait until the socket handlers received some data which cause the handlers to unregister the sockets and timers
    4. at this point, the main event loop has ended. go to next test and setup a new event loop
How do you do (3) and (4) in Node? I have no idea, and I couldn't find any clear answers on the Internet. I ended up writing my tests in RSpec which launch Node processes, and I just check whether the stuff printed to stdout matches what I expect. RSpec also happens to have a much much nicer syntax than any Javascript testing framework I've encountered.


Check out tap, it has a very simple api that works well for testing asynchronous code: https://github.com/isaacs/node-tap

Here's a tap example that sets up a server and client for dnode: https://github.com/substack/dnode/blob/master/test/single.js

Timers usually aren't necessary with test harnesses like tap or nodeunit since you need to call `t.end()` explicitly or else `t.plan()` the number of tests that are supposed to be run. If a different number of tests actually run or assertions fire after `t.end()` is called, those are reported as errors.

For (4), to run a bunch of test files in a directory you can use the `tap` command. You can even add something like `tap test/*.js` to the scripts.test field of a package.json file and then to run all your tests you can just do `npm test`.


That sounds like a complicated approach at it. Here's an example of some NodeUnit tests that involve communications with a Redis-based message queue:

https://github.com/bergie/noflo/blob/master/test/MQ_SendMess...

More BDD-ish version of something similar:

https://github.com/nemein/kckupmq/blob/master/test/001_kckup...


Does that test you link actually talk to a live Redis-based message queue that must exist for the test to run?

If so, while that's a nice test there's also a need to be able to fully control the event loop so you can test arbitrary event orders, some of which you may not be able to synthesize (or not easily, or not reliably) but may be able to occur in the real world. Testing event loop code sucks hard enough when you can fake events perfectly correctly, take that away and it sucks even worse.


>there's also a need to be able to fully control the event loop so you can test arbitrary event orders

Hmm, something doesn't sound right there. I'm not really sure why you'd want to "fully control the event loop" for testing, but if you did you can install a callback on every tick: http://nodejs.org/api/process.html#process_process_nexttick_...

If you want to test arbitrary inbound event sequences, you'll need to run at least two processes. You could run two node processes, one generating events for the other. This would probably give you a better test environment then hacking the event loop, too.


"I'm not really sure why you'd want to "fully control the event loop" for testing,"

Because while I'm actually one of the first to tell you that not everything needs to be a unit test and I tend to prefer integration tests over unit tests if given a choice, I will also say that unit tests still have their place, and the way you unit test an event-driven program is to feed the events you specify to an event loop and ensure that the proper actions taken, using whatever is necessary to ensure proper independence.

It's nice to be able to do integration tests, it is not nice to have to do integration tests.

You know, this may explain a great deal of the gap between my opinion of event-based programming and the conventional Node opinion. Testing event-based code isn't necessarily that hard (testing is never really easy in a language where you're always in the local IO monad equivalent, though cracking it up into events does make things challenging, especially if you try to take advantage of closures in your handlers, which unfortunately is advantageous in other ways but hurts testability hard) but it doesn't help that the frameworks never seem to ship with the testing support I just specified and I'm always having to bash it together myself, which tends to show a certain... disconnect in expectations between me and the authors.


There's also mocha: http://visionmedia.github.com/mocha/

Which has very similar syntax to RSpec.


Try writing tests for controllers with Mocha. It isn't as simple as one might think.


Can you elaborate? I feel that I've written tests for controllers with Mocha several times without much hassle. Maybe you and I are using the word "controller" slightly differently, or are controlling different things?


My apologies I wasn't too specific. I was meaning a controller through express. It's not as straightforward as you would expect with code buried throughout on how to set it up. This is a typical barrier for developers to not test as much.


Express doesn't even have controllers though -- just a routing mechanism.

If you set up your controllers so that they are independent from the routes, then they are just as easy to test.

It could be as simple as: app.get('/users/:id', userController.userPage). You can then test userController.userPage(req, res, next) instead of the route.


True, but in the case of the app I need to start a test server and such. Its those steps that aren't well documented and can cause confusion.


#3 I'm not undestanding. Are you doing async? I don't know the socket API but it should be something like this:

it("should wait for socket", function(done) { socket.write("asdfadf", function(err, response) { assert.ok(response.indexOf('token') >= ); done() ); });

#4 If you need a new event loop then write the tests in another module, then simply run your test utility. `mocha` will run all tests in test/*test.js.

RSpec is DOG SLOW! I can run 100s of test in a couple of seconds. Can RSpec even startup in that time?


>RSpec is DOG SLOW! I can run 100s of test in a couple of seconds. Can RSpec even startup in that time?

Yes, of course it can. RSpec is not especially slow. Obviously the ruby interpreter can be slow, for any given rspec test you could write something faster in C or Java or Go or whatever. That's irrelevant.

I'm guessing you're referring to rails tests, where the whole rails stack has to be loaded with each run of the test suite, something that is notoriously slow. There are strategies to avoid this.

Also it is very easy for the naive rails developer to write tests with extremely inefficient usage of the database, which creates horrible bottlenecks.


I presume it would be something related to capybara, rspec and factory girl.


Looking at the example of integrating those on RSpec's docs page... pretty nice.

https://github.com/rspec/rspec-rails

My guess is a similar Node cocktail would be using Mocha, Tobi, and Should.js together.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: