Skip to main content

Getting Started

See how to create tests in an Athenna application.

Introduction

Athenna is built with testing in mind. In fact, support for testing with Japa is included out of the box. The framework also ships with convenient helper methods that allow you to expressively test your applications.

By default, your application's tests directory contains two directories:

  • e2e - Should contains the tests responsible to test a larger portion of your code, including how several object interact with each other or even a full HTTP request to a JSON endpoint.
  • unit - Should contains the tests responsible to test isolated portion of your code, focusing on a single method. Tests within your unit test directory should not boot your Athenna application, meaning that they should be unable to access your application's database or other framework services.

The e2e/AppControllerTest.ts and unit/AppServiceTest.ts files are provided for you to use as an example to start writing your own tests. After installing a new Athenna application, execute the following to run your tests:

node artisan test

Environment

By default Athenna comes set with the configuration environment as test, meaning that the .env.test file will be used when running your tests.

You are free to define other testing environment value. To do that you can change the env value of your test command inside of your .athennarc.json file:

.athennarc.json
{
"commands": {
"test": {
"path": "@athenna/core/commands/TestCommand",
"env": "my-custom-env",
"loadApp": true,
"stayAlive": true
}
}
}
tip

You can also use the --env flag to set the environment:

node artisan test --env testing

Writing tests

To create a new test case, use the make:test Artisan command. By default, tests will be placed in the tests/e2e directory:

node artisan make:test UserTest

If you would like to create a test within the tests/unit directory, you may use the --unit option when executing the make:test command:

node artisan make:test UserTest --unit
tip

You can also create a custom test for each specific Athenna application:

For REST API
node artisan make:test UserTest --rest
For CLI
node artisan make:test UserTest --console

To customize the test templates check the template:customize command.

Once the test has been generated, you may define your test methods and annotate them with the @Test() annotation:

import { Test, type Context } from '@athenna/test'

export default class ExampleTest {
@Test()
public async testBasicExample({ assert }: Context) {
assert.equal(1 + 1, 2)
}
}

Tests structure

Athenna tests are represented as classes. Your class name will be used as the test suite name, while the test methods will be considered the test names. All the methods of the class are customizable, what defines if that method is a test, test hook or even a helper method is the annotation used:

import { 
Test,
BeforeAll,
BeforeEach,
AfterAll,
AfterEach,
type Context
} from '@athenna/test'

export default class SumTest {
public sum(a: number, b: number): number {
return a + b
}

@BeforeAll()
public async beforeAll() {
//
}

@AfterAll()
public async afterAll() {
//
}

@BeforeEach()
public async beforeEach() {
//
}

@AfterEach()
public async afterEach() {
//
}

@Test()
public async 'should be considered a test!' ({ assert }: Context) {
assert.equal(this.sum(1, 1), 2)
}
}

@Test()

The @Test() annotation is used to define a method as a test:

@Test()
public async testMethod({ assert }: Context) {
assert.equal(1 + 1, 2)
}

You can also define the test name by passing a string to the @Test() annotation:

@Test('test method!')
public async testMethod({ assert }: Context) {
assert.equal(1 + 1, 2)
}
tip

This could also be done in class defining the method name as string:

@Test()
public async 'test method!' ({ assert }: Context) {
assert.equal(1 + 1, 2)
}

@BeforeAll()

The @BeforeAll() annotation is used to define that a method should be executed before all tests of that class starts running. You can define as many as you want in the same class:

@BeforeAll()
public async doSomeOp() {
//
}

@BeforeAll()
public async doOtherOp() {
//
}

@BeforeEach()

The @BeforeEach() annotation is used to define that a method should be executed before each tests of that class starts running. You can define as many as you want in the same class:

@BeforeEach()
public async doSomeOp() {
//
}

@BeforeEach()
public async doOtherOp() {
//
}

@AfterAll()

The @AfterAll() annotation is used to define that a method should be executed after all tests of that class ends running. You can define as many as you want in the same class:

@AfterAll()
public async doSomeOp() {
//
}

@AfterAll()
public async doOtherOp() {
//
}

@AfterEach()

The @AfterEach() annotation is used to define that a method should be executed after each tests of that class ends running. You can define as many as you want in the same class:

@AfterEach()
public async doSomeOp() {
//
}

@AfterEach()
public async doOtherOp() {
//
}

Running tests

To run your tests you can use the test Artisan command:

node artisan test

Any arguments that can be passed to Japa, may also be passed to the Artisan test command:

node artisan test --groups="MyClassTest" --force-exit

Assertions

Athenna ships with a variety of helpful assertions with the help of the @japa/assert plugin. We are not going to cover the assertions here, but you can check the assert documentation section of Japa to see all the available methods for you.

Their documentation is beautiful, small and precise. I swear it will be worth your time 😎.

Other useful annotations

Along with the annotations seen above, Athenna ships with other useful annotations that can be used to customize how your test is going to behave. You can check all of them and it options in the testing annotations documentation section

Reporting test coverage

When running your application tests, you may want to determine whether your test cases are actually covering the application code and how much application code is used when running your tests.

To accomplish this, you may use the c8 tool that already comes installed and configured for you in your application. To use it, you just need to call it before invoking the test command:

npx c8 node artisan test
note

By default, Athenna already comes with the test:coverage npm script defined that already does this job for you:

npm run test:coverage

Creating base test classes

If you would like to define some helper methods to be defined in all your test classes, you can create a base test class and extend it in your tests:

tests/helpers/BaseTest.ts
import { BeforeAll } from '@athenna/test'

export class BaseTest {
@BeforeAll()
public async beforeAll() {
console.log('Executed before all tests that extends BaseTest!')
}

public getMockedData() {
return {
name: 'Lenon'
}
}
}
tests/e2e/UserTest.ts
import { Test, type Context } from '@athenna/test'
import { BaseTest } from '#tests/helpers/BaseTest'

export default class UserTest extends BaseTest {
@Test()
public async test({ assert }: Context) {
const data = this.getMockedData()

assert.equal(data.name, 'Lenon')
}
}