Help:Pickle/Quick tour

This is the original documentation for the module before repackaging. The module is not ready for production.

The purpose of this module is to support testing in behavior-driven development (BDD), a software development process that emerged from test-driven development (TDD), in on-going development of modules written in Lua. It makes an assumption of a test module on a separate page, possibly a subpage, and presentation on another page like the talk page or generated through an API call.

The module mimics some ideas from other BDD libs, like RSpec [1], Jasmine [2], and Busted [3]. There are no clear standard on how to do this, so there are some variation and adaption.

The module is not built for great speed, it uses closures to build a number of small objects, that is methods returns a value that holds a closure. This creates a fairly efficient implementation for simple access, but it is not very efficient for caching larger structures. Some larger structures are put in tables and built once. This is done for Expect where each new instance would otherwise create a lot of methods.

The module avoids as much caching as possible, as this can poison the tests.


If you have a module like «Module:HelloWorld», the ubiquitous and quite pesky example, coded as something like

local p = {}

function p.helloWorld()
	return "Hi there!"

return p

Then on a test page you would test this like like the following

require 'Module:BDD'()
local p = require 'Module:HelloWorld'()

describe('Hello world', function()
	context('On all pages', function()
		it('says hello', function()
			expect('p.helloWorld()', p.helloWorld()):toBe("Hi there!");

return result('Module:HelloWorld')

In the first line the test framework is not only loaded, but it is also installed in the global name space. The trailing parenthesis is a call on the loaded table, and it will install additional global functions. It is not necessary to keep a pointer to the test framework, the functions keep their own pointers.

In the second line the module under test is loaded. Usually it is necessary to keep a pointer to the returned value.

The describe function adds a title and evaluates the function from a xpcall (not done yet). The same happens with context and it. These three are really the same, it is only our interpretation that changes.

The expect function adds a comment and the statement that creates the actual value. It then builds a closure and returns a structure in a flow style. This makes it possible to manipulate the instance, before we finally evaluates it and stores the result for later visualization. In this case we simply tests it to see if it is equal.

The final results are returned by a call to result. Like before this can add a title.

The tests can be prepared for for localization into several languages, for example English and Norwegian Bokmål

require 'Module:BDD'()
local p = require 'Module:HelloWorld'()

describe({en='Hello world', nb='Hallo verden'}, function()
	context({en='on all pages', nb='på alle sider'}, function()
		it({en='says hello', nb='sier hallo'}, function()
			expect('p.helloWorld()', p.helloWorld()):toBe("Hi there!");

return result({ en='Module:HelloWorld', nb='Module:HelloWorld'})

In this case the languages will be chosen according to the site content language, and if that isn't defined it will use the languages from the fallback chain. If the first argument is a string, then that string will always be used. The language can be changed if the tests are run through the api, which makes it easy to check tests if they are prepared for the requested language.

Usually it is good practice to both use a common language to make the tests readable and reusable, and use a local language to make them readable for the local community at each project.