bigtestjs / server

All BigTest development has moved to https://github.com/thefrontside/bigtest
https://github.com/thefrontside/bigtest
2 stars 1 forks source link

Add test suite #21

Closed cowboyd closed 4 years ago

cowboyd commented 4 years ago

Thus far we've been developing without tests which has been a necessary as we even attempt to map the landscape. However, it looks like very soon we will be transitioning from a pure research mode into actually having a product that will be able to do more and more useful and complex things. If so, then we'll need to have a way to automatically test it.

This change introduces a very minimal test suite that nevertheless tries to be as "Big" as possible. It starts the entire server before each test case, and then shuts it down after each test case, and only ever interacts with it over http.

In order to make this work I had to make some changes to the way the code is organized internally.

Parcel Bundler

It appears that Parcel does not shut down cleanly if stop() is called too soon after start(). After a delay of about 500ms, it will shutdown cleanly, but before that it leaks listeners and processes and hangs the instance of node from which it was invoked. I guess they didn't get the memo to use effection :)

To get around this, I just forked the bundler as a separate process which appears to work the same, but forces a clean shutdown, because parcel itself will invoke process.exit() to forcibly kill itself. This ought to be ok because under the covers, the Bundler#bundle() method is forking out three or four child processes anyway, so we're not realy saving anything by running the main bundler in-process.

The tradeoff is that we don't actually have a reference to the object so we can't know what its state of readiness is.

We might be able to figure out what's going on with Parcel and help it to shutdown cleanly and contribute that back to the project.

Logging

Another change I had to make was to the logging. With the amount of logging that we were doing in our testcases, the test console was really ugly. It's more of a workaround rather than anything else, but I delegated the console.log() function through an importable logger module that can be replaced at runtime in the test cases.

Hello World

Finally, to make sure that absolutely everything gets torn down properly after each testcase, everything async happens through a World object which is destroyed at the end. If we want to run an effection Operation, you would do it with world.fork() and it will be halted at the end. Even non-effection APIs should be adapted to happen in the World object, that way they too will be halted at the end. For an example of this, we can see the get() method which uses a promise.

Finally, the test suite itself is defined using mocha, but uses the strict Arrange/Act/Assert or Given/When/Then format. I imagine that we'll eventually want to dogfood our new syntax for expressing test suites, but that can come later.

TODOS / Open Questions