I’m sure you are reading this and thinking:
That was my first thought as well. I was working on a project and decided I wanted to add some unit tests. I tried AVA. Then I tried Tape. Then Mocha. Then Jest. Three hours later I was right back where I started. Nothing worked out of the box. I was stuck battling with Babel configs, ES6 modules failing to be imported/resolved, external dependencies, testing configs, etc. I grew more and more frustrated.
As someone who has been writing software for quite a while now, if I’m having this much trouble, then I can only imagine what new developers must be going through. I suspect a lot of people give up and end up not writing any tests at all.
Now is the part where readers will chime in:
But sir, clearly you must be a moron. I use those frameworks and they are so easy to set up. It takes a couple minutes to get up and running.
Congratulations. I am happy for you. I’m not saying my experience is shared by everyone. It really depends on the specific project you are working on.
Karma, Mocha, Jasmine, Jest, Sinon, Chai, AVA, Babel, Gulp, Grunt, Webpack, Buble, Rollup, jsdom just to name a few.
There is a kaleidoscope of boilerplate code that you have to write before you can write a single test. I counted over 50 configuration options in the Karma documentation and many of those have their own set of sub-options! The fact that Karma is a runner for other unit test runners and that the intro video is around 15 minutes long should tell you everything you need to know.
Most testing frameworks require plugins or other tools to do simple things like code coverage. It may not necessarily be difficult to add, but it is still an extra step you have to take.
I have been writing a lot of go lately, and something that I really like is how go’s testing is built directly into the language. You can literally create a file, add some tests, and run them without having to install any external dependencies.
This is part of what inspired me to create Luna. I was looking for a unit testing framework that just worked and did not require any crazy configuration or external libraries. I wanted to be able to add a test function anywhere in my code, run the test, and see the result.
As a result, Luna has no configuration at all.
In order to achieve this it does make some assumptions about the environment you are working in. Your tests have to be written as ES6 modules, and your code should be too. Luna does not transpile any source code with the exception of JSX. This means if you are using Coffeescript or Typescript you will be out of luck right now.
Luna searches for any functions whose names begin with
test that are exported from whatever files and directories you tell it to look in. It then uses rollup’s API to dynamically create a test running bundle in memory. Each test function is called and passed an instance of an object with a single
assert method. The results are communicated back to the main process using console logs.
This means everything is self contained and there are no global variables required. In addition, you do not need to import any custom libraries to run your tests since the test functions themselves get pulled out of your code.
- Because of the way Luna works you can include test functions anywhere you want including in your source files themselves. Note: This is only recommended if you are using tree shaking when you build your production bundles to strip out the test code.
- Browser testing is built in and runs by default. It uses puppeteer to run in a recent version of Chromium.
- It supports concurrency using a backpressure queue to allow tests to run in parallel. This is useful if some tests are CPU intensive or take a while to run.
- It generates code coverage reports automatically without having to install any additional libraries (pass the
--no-coverageflag to disable them).
- Luna will translate and apply source maps automatically to code coverage reports and stack traces when your tests have an error even though Puppeteer does not support them.
- The assert function used by Luna is inspired by power-assert so if your test fails, you can see exactly which part of the statement failed instead of a generic message like:
Failed asserting that false is true. Here is an example output for a failed test:
25 t.assert(data3.message = 'Something should be false');
"Something should be true"
- It supports comparisons to arrays and objects without having to use any custom syntax (just use
!=for the comparison):
t.assert(list == ['one', 'two', 'three']);
- It compiles JSX code automatically into
- The tests for Luna are run by Luna. How meta!
You can find out more and read the full documentation on GitHub.
Also be sure to check out the project introduction page.