I have seen quite a lot of talking about test, and tried a little RSpec when learning Ruby on Rails years ago. But I don’t really get myself dig into the testing world. Today is Sunday, it’s a sudden that come to my mind that maybe I should spend some time figure it out.
It’s a sad fact that the company I am working never encourage writing test for project. It relays a lot on human QA. Well that’s not bad in some sense. But apparently we can be more efficient and get less bug if we adopt automated test. There seems to be architecture change in term of development. I found it a good chance to add test to the new architecture.
I just spend an afternoon make the test working for the nba-daily project that I have worked months ago. It has similar idea behind the company project, which proxying site to a better UI. In the mind, the test should be to pretty simple, namely, going to a page, checking that page contains what we need, going to another page, checking again.
Check element is pretty common in testing. Most test framework and assert library should already taken then cared. The only thing is to requesting page. Obviously we cannot use node’s plane http request module because if the real project, the request has to maintain the cookie and session. Normally cookie and session is handled by browser, so my first head to find those browser testing tools. It turns out that there is thing called Selenium, which can opens up local or remote browser, and use the browser to make the request. It can use different web driver to drive different browser. I tried the
chai-webdriver and chrome driver, it works, but it won’t work on the Travis CI, which doesn’t have a browser GUI. To make Travis work, we need to use remote browser on virtual machine. I know that I have pay to use that.
Then it come up another solution, PhantomJS. It call itself
real browser. At this point, I get everything I need.
I pick up the most used (or most famous) test tool, mocha and chai to construct the test case. Soon I found that the assert need to be async. It need to assert after the request is done. Mocha provide a very nice way to achieve, simply call the done() function after asynchronously assert. A very nice thing about phantomjs here is that, one of my request is based on the ajax call on the page. As long as I set a few seconds timeout to wait for the request is done, test is totally working!
When I try to intentionally fail the test, gotcha occur. When I fail the first test, the rest tests all get timeouted error. It wired, since if one failed, the test should show that they should show, either success or fail, why it’s a timeout error? It turns out that, when a async test failed, the assert will throw an error. So the following done() function will never run, which make the rest tests timeout. The solution is to wrap a try catch to assert and done, and call done again in the catch with e as params. So when assert failed, done will still get called.
After all test working locally, the deployment just work out of the box. Travis will automatically run
npm test if there is one in the package.json. So I send a pr, all build and test start running automatically. After a while, pass all green. yay!