Skip to main content

Annotations

Check all available testing annotations and it options.

@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() {
//
}

@Retry()

Define that a test should be retried if it fails:

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

export default class ExampleTest {
@Test()
@Retry(2) 👈 // Retry the test 2 times
public async test({ assert }: Context) {
assert.equal(1 + 1, 2)
}
}
tip

You can get the number of retries and in which retry attempt you are by the test.options.retries and test.options.retryAttempt properties

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

export default class ExampleTest {
@Test()
@Retry(2)
public async test({ test, assert }: Context) {
Log.info('Retrying attempt:', test.options.retryAttempt)

assert.equal(1 + 1, 2)
assert.equal(test.options.retries, 2)
}
}

@Skip()

Skip the test when executing test command:

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

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

@Test()
@Skip('Skipped because of some reason')
public async willNotRunAlso({ assert }: Context) {
assert.equal(1 + 1, 2)
}
}

@Pin()

When running test command, only pinned tests will run if at least one test is pinned:

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

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

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

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

If you want to run specific tests you can also use the --tests option of test command:

node artisan test --tests willRun --tests willRunAlso

@Fails()

Define that a test is expected to fail:

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

export default class ExampleTest {
@Test()
@Fails()
public async test({ assert }: Context) {
assert.equal(1 + 1, 1) 👈 // Fail
}
}

@TestCase()

Define the dataset for the test case. Your test will be invoked for each test case defined:

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

export default class ExampleTest {
@Test()
@TestCase('lenon@athenna.io')
@TestCase('txsoura@athenna.io')
public async test({ assert }: Context, email: string) {
assert.isTrue(email.includes('@athenna.io'))
}
}
tip

You can get all the test cases defined by the test.dataset property:

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

export default class ExampleTest {
@Test()
@TestCase('lenon@athenna.io')
@TestCase('txsoura@athenna.io')
public async test({ test, assert }: Context, email: string) {
assert.isTrue(email.includes('@athenna.io'))
assert.deepEqual(test.dataset, [
'txsoura@athenna.io',
'lenon@athenna.io'
])
}
}

@Timeout()

Set a timeout in MS for that specific test only:

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

export default class ExampleTest {
@Test()
@Timeout(10000) 👈 // 10 seconds
public async test({ assert }: Context) {
assert.equal(1 + 1, 2)
}
}

@DisableTimeout()

Disable the timeout for a specific test:

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

export default class ExampleTest {
@Test()
@DisableTimeout(10000) 👈 // 10 seconds
public async test({ assert }: Context) {
assert.equal(1 + 1, 2)
}
}

@Tags()

Add tags to a test. Tags can be used to filter tests when running test command:

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

export default class ExampleTest {
@Test()
@Tags(['run'])
public async willRun({ assert }: Context) {
assert.equal(1 + 1, 2)
}

@Test()
@Tags(['run'])
public async willRunAlso({ assert }: Context) {
assert.equal(1 + 1, 2)
}

@Test()
@Tags(['dont-run'])
public async willNotRun({ assert }: Context) {
assert.equal(1 + 1, 2)
}
}

Now you can select which tests to run by the tags:

node artisan test --tags run

@Cleanup()

Create a cleanup function with the purpose to clean the state created by your test. This function will always be executed, even if your test fails:

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

export default class ExampleTest {
@Test()
@Cleanup(() => Config.set('app.name', 'Athenna'))
public async test({ assert }: Context) {
Config.set('app.name', 'MyApp')

assert.equal(Config.get('app.name'), 'MyApp')
}
}

@Setup()

@Setup() annotation works like @BeforeEach() but for a specific test. The function you define inside will be called before the test starts running:

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

export default class ExampleTest {
@Test()
@Setup(() => Config.set('app.name', 'MyApp'))
public async test({ assert }: Context) {
assert.equal(Config.get('app.name'), 'MyApp')
}
}

@Teardown()

@Teardown() annotation works like @AfterEach() but for a specific test. The function you define inside will be called after the test finish running:

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

export default class ExampleTest {
@Test()
@Setup(() => Config.set('app.name', 'MyApp'))
@Teardown(() => Config.set('app.name', 'Athenna'))
public async test({ assert }: Context) {
assert.equal(Config.get('app.name'), 'MyApp')
}
}