Skip to content

A Lua library for testing your code. It does for Lua what Jest does for JS, with the same API.

License

Notifications You must be signed in to change notification settings

luttje/jestronaut

Repository files navigation

Warning Jestronaut is still in early development.

Jestronaut logo showing a jester in a space helmet

Jestronaut

License LuaRocks GitHub Tests Action Dependency status Test Coverage Status

A Lua library for testing your code. It does for Lua what Jest does for JavaScript, with the same API.

Jestronaut allows you to assert, mock, and spy on your code with ease. It includes a test-runner that you can start from the CLI or Lua:

Jestronaut output showing green signals besides all tests in 4 files to indicate the tests inside passed

For this GIF the tests were run with the verbose and 200ms slowDown settings. Some frames were cut to prevent flickering. The actual duration of these tests was around 0.043s

🚀 Getting Started

First create a test file inside your project, for example:

-- tests/my_test.lua
describe("my test", function()
  it("should pass", function()
    expect(1 + 1):toBe(2)
  end)
end)

Then you can choose one of two ways to run the tests with Jestronaut, either run it with LuaRocks OR download the standalone binary and run tests anywhere.

Run in project with LuaRocks

Note Before continuing, make sure you have installed LuaRocks with at least Lua 5.1.

  1. Install Jestronaut as a LuaRocks module in your project

    luarocks install jestronaut
  2. Create a test runner file in the root of your project named test.lua:

    require "jestronaut":withGlobals()
    
    jestronaut
      :configure({
        roots = {
          "./tests/", -- Directory where you saved the test file above
        },
      })
      :registerTests(function()
        package.path = package.path .. ";./tests/?.lua"
        require "my_test"
      end)
      :runTests()
  3. In the root of your project, start your tests using LuaRocks: luarocks test or with plain Lua: lua test.lua.

Running tests with lit binary

This binary is a standalone executable that can be used to run Jestronaut tests anywhere.

  1. Download the latest binary from the releases page.

  2. Install the binary somewhere in your PATH and make sure it's named jestronaut (or jestronaut.exe on Windows)

  3. Run the tests with jestronaut, for example:

    MSYS_NO_PATHCONV=1 jestronaut \
      --roots=./tests/generated \
      --roots=./tests \
      --testPathIgnorePatterns="/tests/generated/ExpectAPI/toBeCloseTo.lua$/" \
      --testPathIgnorePatterns="/tests/generated/GlobalAPI/test.lua$/"

    Note

    The variable MSYS_NO_PATHCONV=1 is only required on Windows when using MSYS2 (for example with Git for Windows). It prevents the path from being converted to a Windows path, which would result in an incorrect path.

🧪 API

Jestronaut tries to match the API of Jest as closely as possible. Here are some examples of how to use it:

describe("test organization into suites", function()
  it("should confirm basic math", function()
    expect(1 + 1):toBe(2)      
  end)
end)

it("should let sums NOT match", function()
  expect(1 + 1)['not']:toBe(3)
  expect(1 + 5)['not']:toBeGreaterThan(7)
end)

it("should have all the matchers Jest has", function()
  expect(1 + 1):toBe(2)
  expect(0.1 + 5.2):toBeCloseTo(5.3)
  expect({}):toBeDefined()
  expect(nil):toBeFalsy()
  expect(1 + 1):toBeGreaterThan(1)
  expect(1 + 1):toBeGreaterThanOrEqual(2)
  expect(1 + 1):toBeLessThan(3)
  expect(1 + 1):toBeLessThanOrEqual(2)
  expect(0/0):toBeNaN()
  expect(nil):toBeNil()
  expect(nil):toBeNull()
  expect(1 + 1):toBeTruthy()
  expect(1 + 1):toBeType('number')
  expect(nil):toBeUndefined()
  expect({1, 2, 3}):toContain(2)
  expect({1, 2, 3}):toContainEqual(2)
  expect({1, 2, 3}):toEqual({1, 2, 3})
  expect({1, 2, 3}):toHaveLength(3)
  expect({
    a = 1,
    b = 2,
    c = 3
  }):toHaveProperty('a')
  expect("abc"):toMatch("c$") -- Lua patterns
  expect({
    a = 1,
    b = 2,
    c = 3
  }):toMatchObject({
    a = 1,
    b = 2
  })
  expect({}):toStrictEqual({})
  expect(function() error('test') end):toThrow('test')
  expect(function() error('testing') end):toThrowError('testing')
end)

it('should be able to mock function implementations', function()
  local mockFn = jestronaut:fn(function() return 'x', 'y', 'z' end)
  mockFn(1, 2, 3)

  expect(mockFn):toHaveBeenCalled()
  expect(mockFn):toHaveBeenCalledTimes(1)
  expect(mockFn):toHaveBeenCalledWith(1, 2, 3)
  
  mockFn(3, 2, 1)
  expect(mockFn):toHaveBeenLastCalledWith(3, 2, 1)
  expect(mockFn):toHaveBeenNthCalledWith(1, 1, 2, 3)
  expect(mockFn):toHaveLastReturnedWith('x', 'y', 'z')
  expect(mockFn):toHaveNthReturnedWith(1, 'x', 'y', 'z')
  expect(mockFn):toHaveReturned()
  expect(mockFn):toHaveReturnedTimes(2)
  expect(mockFn):toHaveReturnedWith('x', 'y', 'z')
end)

local ranBefore = 0
beforeAll(function()
  ranBefore = ranBefore + 1
end)

it('should run beforeAll for each "it" this checks how many (so far)', function()
  expect(ranBefore):toEqual(5)
end)

it('can spy on a property setter', function()
  local audio = {
    volume = 0,
  }
  local spy = jestronaut:spyOn(audio, 'volume', 'set')
  audio.volume = 100

  expect(spy):toHaveBeenCalled()
  expect(audio.volume):toBe(100)
end)

it('can spy on a property getter', function()
  local audio = {
    volume = 0,
  }
  local spy = jestronaut:spyOn(audio, 'volume', 'get')
  print(audio.volume)

  expect(spy):toHaveBeenCalled()
  expect(audio.volume):toBe(0)
end)

it:failing('should be able to expected failures', function()
  expect(1 + 1):toEqual(1)
end)

it:skip('should be able to skip tests', function()
  expect(1 + 1):toEqual(1)
end)

it:each({{1, 1, 2}, {1, 2, 3}, {2, 1, 3}})(
  "can loop data (%i, %i = %i)",
  function(a, b, expected)
    expect(a + b):toBe(expected)
  end
)

Check out the Jestronaut tests for more examples.

🦾 Contributing

Note Before continuing, make sure you have installed:

Building

To build Jestronaut, run the following command:

npm run build

This builds the LuaRocks module and lit binary.

This will generate a jestronaut binary in the dist directory of this project. It expects to be added to path and will currently only run tests if you execute jestronaut in the root of your project

Jestronaut's own Tests

Most of Jestronaut's own tests are generated from the Jest documentation automatically.

You can run the test generation script with npm run generate-tests. All tests in tests/generated will be overwritten.

Use luarocks test in the root of this repo to execute the Jestronaut tests.

For coverage install the following LuaRocks modules:

  • luarocks install luacov
  • luarocks install luacov-reporter-lcov

About

A Lua library for testing your code. It does for Lua what Jest does for JS, with the same API.

Resources

License

Stars

Watchers

Forks