Skip to main content

Testing Our Code

In this chapter, we'll extract the has_hello function into its own module and write tests for it using busted.

Testing Framework

In Lua, testing is primarily done using the busted testing framework. Lux takes care of installing busted for you when running tests!

Extracting the module

We'll move has_hello into its own file so our tests can import it directly. Create a new file called src/has_hello.lua and move the function there:

src/has_hello.lua
--- Checks whether input has the word "hello"
---@param input string
local function has_hello(input)
return input:lower():find("hello") ~= nil
end

return {
has_hello = has_hello,
}

Next, let's update our main.lua file to use this new file:

src/main.lua
local has_hello = require("has_hello").has_hello
local argparse = require("argparse")

-- Create an argument parser
local parser = argparse("script", "An example.")
parser:argument("input", "Input file.")

local args = parser:parse()

-- Directly print out the "input" argument
if has_hello(args.input) then
print("Your input has the word 'hello' in it!")
else
print("Your input does not have the word 'hello' in it!")
end

Noticed how we replaced the function with a require call to the new file.

Writing our First Test

Now that we have our code structured, let's write our first test. Tests are usually stored in a spec/ directory, and each test file must end in _spec.lua. Create a new directory called spec/ in the root of your project:

mkdir spec

Inside the spec/ directory, create a new file called has_hello_spec.lua:

spec/has_hello_spec.lua
local has_hello = require("has_hello").has_hello

describe("has_hello", function()
it("should return true if input has the word 'hello'", function()
assert.is_true(has_hello("hello world"))
end)

it("should return false if input does not have the word 'hello'", function()
assert.is_false(has_hello("world"))
end)
end)

Configuring the project to use busted

Before we run the tests, we need to tell Lux that we want to use busted as the test runner. Add this to the bottom of your lux.toml:

test specification
[test]
type = "busted"

Running the Tests

We're now ready to run our tests! lx test will run all the tests in your project. After taking a moment to install busted, Lux should show you the following output:

lx test
●●
2 successes / 0 failures / 0 errors / 0 pending : 0.001615 seconds

If so, congratulations! You've successfully written and ran your first test!

Now let's see what happens when a test fails. Open src/has_hello.lua and change the word "hello" to "hi" in the find call:

return input:lower():find("hi") ~= nil

Run lx test again:

lx test

You should see one test pass and one fail. The second test expects the function to return false when the input doesn't contain "hello", but now it looks for "hi" instead. Change it back to "hello" and re-run to confirm both tests pass again.

Take a look at the busted documentation for more patterns and matchers you can use in your tests.