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:
{
"commands": {
"test": {
"path": "@athenna/core/commands/TestCommand",
"env": "my-custom-env",
"loadApp": true,
"stayAlive": true
}
}
}
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
You can also create a custom test for each specific Athenna application:
node artisan make:test UserTest --rest
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)
}
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
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:
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'
}
}
}
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')
}
}