DEV Community

Cover image for Running Tests Inside QuickJS with TestRunner
Sebastian Wessel
Sebastian Wessel

Posted on

Running Tests Inside QuickJS with TestRunner

The TestRunner is a lightweight testing library that allows you to write and run tests for JavaScript code with ease. It provides a simple interface for defining test suites, tests, and hooks with support for asynchronous code and configurable timeouts. The library also includes Chai's expect function for assertions.

Benefits of Running Tests in a Sandbox

Running tests in a sandbox environment like QuickJS provides several benefits:

  • Isolation: Each test runs in a separate environment, ensuring no side effects between tests.
  • Security: A sandboxed environment limits the potential for malicious code to affect the host system.
  • Consistency: Ensures that tests are run in a controlled environment, leading to more consistent and reliable results.

Importing the Library

To use the TestRunner library in your tests, you need to import it. You also need to ensure that the result of runTests is exported.

import 'testRunner'
Enter fullscreen mode Exit fullscreen mode

Writing Tests

Developers should feel comfortable using the TestRunner as it follows the general approach used in the JavaScript testing ecosystem, similar to Mocha or Jasmine.

Defining a Test Suite

A test suite is defined using the describe function. Inside a test suite, you can define multiple tests using the it function.

describe('Sample Test Suite', () => {
  it('should pass this test', () => {
    expect(true).to.be.true;
  });

  it('should fail this test', () => {
    expect(false).to.be.true;
  });
});
Enter fullscreen mode Exit fullscreen mode

Using Hooks

Hooks are functions that run before or after tests in a suite. The available hooks are:

  • beforeAll: Runs once before all tests in the suite.
  • afterAll: Runs once after all tests in the suite.
  • beforeEach: Runs before each test in the suite.
  • afterEach: Runs after each test in the suite.
describe('Test Suite with Hooks', () => {
  beforeAll(() => {
    console.log('Running beforeAll hook');
  });

  afterAll(() => {
    console.log('Running afterAll hook');
  });

  beforeEach(() => {
    console.log('Running beforeEach hook');
  });

  afterEach(() => {
    console.log('Running afterEach hook');
  });

  it('should pass this test', () => {
    expect(true).to.be.true;
  });
});
Enter fullscreen mode Exit fullscreen mode

Asynchronous Tests and Hooks

The TestRunner supports asynchronous tests and hooks. Simply return a promise or use async/await in your test or hook functions.

describe('Asynchronous Test Suite', () => {
  beforeAll(async () => {
    await new Promise(resolve => setTimeout(resolve, 1000));
  });

  it('should pass this async test', async () => {
    const result = await new Promise(resolve => setTimeout(() => resolve(true), 1000));
    expect(result).to.be.true;
  });
});
Enter fullscreen mode Exit fullscreen mode

Using Chai's expect

The TestRunner includes Chai's expect function for writing assertions in your tests. The expect function is part of Chai's BDD (Behavior-Driven Development) interface. You can learn more about Chai's expect function and its usage at the Chai documentation.

Examples of expect Usage

Here are some examples of using Chai's expect function in your tests:

it('should assert true is true', () => {
  expect(true).to.be.true;
});

it('should assert equality', () => {
  expect(1 + 1).to.equal(2);
});
Enter fullscreen mode Exit fullscreen mode

Running Tests

To run the tests, you need to call runTests and export the result. You can specify a custom timeout for tests and hooks by passing the timeout value in milliseconds as an argument to runTests.

import 'testRunner'

describe('Sample Test Suite', () => {
  it('should pass this test', () => {
    expect(true).to.be.true;
  });

  it('should fail this test', () => {
    expect(false).to.be.true;
  });
});

export default await runTests();
Enter fullscreen mode Exit fullscreen mode

Custom Timeout

You can set a custom timeout for all tests and hooks in the suite by passing the timeout value to runTests.

import 'testRunner'

describe('Sample Test Suite with Custom Timeout', () => {
  it('should pass this test', () => {
    expect(true).to.be.true;
  });

  it('should fail this test', () => {
    expect(false).to.be.true;
  });
});

export default await runTests(10000); // Set timeout to 10 seconds
Enter fullscreen mode Exit fullscreen mode

Example Usage

Here is an example demonstrating the complete setup and usage of the TestRunner library.

import 'testRunner'

describe('Example Test Suite', () => {
  beforeAll(() => {
    console.log('Running global beforeAll hook');
  });

  afterAll(() => {
    console.log('Running global afterAll hook');
  });

  beforeEach(() => {
    console.log('Running global beforeEach hook');
  });

  afterEach(() => {
    console.log('Running global afterEach hook');
  });

  describe('Nested Suite', () => {
    beforeAll(() => {
      console.log('Running nested beforeAll hook');
    });

    it('should pass this test', () => {
      expect(true).to.be.true;
    });

    it('should fail this test', () => {
      expect(false).to.be.true;
    });
  });

  it('should pass this test outside nested suite', () => {
    expect(1 + 1).to.equal(2);
  });
});

export default await runTests();
Enter fullscreen mode Exit fullscreen mode

Conclusion

The TestRunner library provides a straightforward way to define and run tests for your JavaScript code. With support for asynchronous operations, configurable timeouts, and Chai's expect function for assertions, you can ensure that your tests are robust and reliable. Happy testing!


Documentation: https://sebastianwessel.github.io/quickjs/
GitHub Repository: https://github.com/sebastianwessel/quickjs
Submit Feedback: Create an Issue on GitHub

Top comments (0)