Introduction
Last week, I added static analysis tooling to cli-ssg. Continuing the process of managing project complexity, this week I worked on adding automated testing.
There are lots of frameworks to choose from when it comes to automated testing. However, since cli-ssg is built on Node.js, I chose to go with one of the most popular and well supported frameworks, jest to automate the testing process.
Setting up jest
Starting off by simply installing jest:
npm install --save-dev jest
Adding a simple test
script to run jest
through npm
in package.json
:
"scripts":{
"test": "jest"
}
Now, I was able to run the tests using npm test
. I also added a test-watch
script to have jest
watch for changes and run tests automatically when the test or source code is updated:
"scripts":{
"test-watch": "jest --watch --"
}
With jest
configured, it was now time to write tests!
Writing tests:
As a starting point, I started off by testing the Options
module. More specifically, I decided to test the validateInput()
function which validates the this.input
path and returns true if it exists:
validateInput() {
if (!fs.existsSync(this.input)) {
throw new Error(
`${this.input} does not exist. Input path must be a file or directory`
);
}
return true;
}
To test it, I created a configOptions.js
file and after some back and forth this is what I came up, to test all possible scenarios for this function:
describe('validate input tests', () => {
let options;
beforeEach(() => {
options = new Options();
});
test('empty, null and undefined paths should throw error', async () => {
[null, undefined, ''].forEach((p) => {
options.input = p;
expect(() => options.validateInput()).toThrow();
});
});
test('non-existing file should throw error', async () => {
options.input = 'invalidPath';
expect(() => options.validateInput()).toThrow(
'invalidPath does not exist. Input path must be a file or directory'
);
});
test('should validate an existing file', async () => {
fs.existsSync.mockResolvedValue(true);
expect(options.validateInput()).toEqual(true);
});
});
With the first unit test down, I wanted to test the core functionality of the SSG. To do this, I narrowed in on the convertFileToHtml(filePath, stylesheet, lang)
function which converts a .txt
file and generates .html
output.
To test this functionality, I ended up using the beforeEach()
and afterAll
helpers to create and delete a sample input file using which I could then test this function:
beforeEach(() => {
fs.writeFileSync(inputFilePath, fileInput);
});
afterAll(() => {
fs.unlinkSync(inputFilePath);
});
The input scenarios that I tested were quite straightforward:
- html should be generated
- h1 tag should be generated from txt file
- stylesheet attribute should be rendered as a link tag
- lang attribute should be present in html
Takeaways
With jest
configured and some tests already written, we can now work on improving the code coverage. It was nice to setup automated testing since without tests, it's easy to break existing code or introduce unexpected bugs. The good news is that now, the tool can be tested by simply running npm test
:
References
Github repo - https://github.com/dhillonks/cli-ssg
3d3d110 - https://github.com/dhillonks/cli-ssg/commit/3d3d1100350d885a5074a96e9757fa527fcb11c9
Top comments (0)