Why do JavaScript projects tend to have their own folder for tests

testing
javascript

#1

I’m coming from Go learning my way around the frontend, and something I noticed about JS test coverage that’s different from Go is that in JS, it’s popular to make a dedicated folder for tests, while Gophers put their Go tests in the same folder as the files they’re testing (ex have db.go and db_test.go). Is there a reason why dedicated test folders seems to be the go-to practice? Personally I like the Go style because looking at a Go diff in GH, I can quickly scroll between the test coverage and the code it tests, but I haven’t done a big JS project, so I’m interested in hearing about the benefits of the dedicated-folder style.


#2

It’s not a very satisfying answer, but it’s because it’s always been that way. One of the first big front-end JS testing libraries, Jasmine, expected to find all the test modules in one folder. You could configure which folder, but the default was /spec. The reason it did this was so that tests could be run programatically in development, but the spec folder would not be deployed to the production server.

Later, in Node, the Mocha testing library carried on the same way, only now the folder was called test. If you run mocha from the command line (usually via npm test) it runs all the test suites in the test folder.

A newer library Jest bucks the trend. It works nicely with React components (Jest and React are both Facebook products, but they’re not tied to one another), and if you have a component in a file named Widget.js then its test suite will traditionally live in a file named Widget.test.js right beside it in the same folder. Jest will look for such files in the src folder and run them all, usually watching for changes made to the corresponding component files.

A React app is almost certainly going to be bundled with something like webpack before deployment, and since none of the components have their test files as a dependency, none of the test files will be added to the bundle and no tests will be deployed. A vanilla JS app does not necessarily need to be bundled, and so you want to keep test files away from business logic so that they aren’t deployed to production. And although deploying tests matters a little less with Node projects, the common testing library follows the same convention as the most common front-end testing library.


#3

Cool thanks for the explanation!


#4

Not necessarily authoritative, but since JavaScript is usually shipped to the browser, I always thought it was simpler to be able to exclude the tests from the deliverable if they were in a separate folder.

Fwiw, the tests in a separate folder pattern is common to Ruby, C#, and Java as well as I recall.


#5

Indeed. Also true in Android apps (Kotlin, or Java if you like), iOS (Swift and Objective C), and Python. As far as I know, the Go structure described (with test file and code file in the same place) is a bit of an aberration.


#6

I’ve done it both ways. Starting out, I find that having a *.test.js right next to each *.js to be convenient.

But as the codebase grows, that pattern becomes overly restrictive. While refactoring, it may be natural one file to be split out from another, but there’s no need to do the same with the tests. Also, an integration test can cover several files in different directories.

Separate directories keeps the test code decoupled from the production code.


#7

Interesting perspectives! Since dedicated test folders are the norm, it’d be cool if GH had drag and drop to change the order of files in reviews and diffs!


#8

I wondered if a browser extension might exists that adds that functionality for you. A bit of googling turned up this list of extensions for improving the Github experience:

Couldn’t find the drag and drop option you mentioned, but there are some UI enhancements that still be helpful like collapsable diffs and filters. Aside: this lead to me discovering about half a dozen extensions that I didn’t have before but that will certainly come in handy, so trying to help out already paid off for me :stuck_out_tongue: