-
Notifications
You must be signed in to change notification settings - Fork 1
Documentation
This is the official and up-to-date documentation for the GameMaker's Testing Library. Here you will find all the information you need to start using the library in your projects.
- Definitions
- Setup
- Teardown
- Common Matchers
- Truthiness
- Numbers
- never
-
Simulations
- create
- simulateKeyPress
- simulateKeyRelease
- simulateKeyHold
- simulateGamepadButtonPress
- simulateGamepadButtonRelease
- simulateGamepadButtonHold
- simulateMouseClickPress
- simulateMouseClickRelease
- simulateMouseClickHold
- simulateMousePosition
- simulateFrameWait
- simulateEvent
- simulateTimesource
- simulateCallLater
Note
Definitions were added in v1.1.0 to allow users to configure the library's behavior without modifying the library's code directly. Previous versions of the library do not have this feature so this section would not apply to them.
Here you will find some of the definitions that are user editable for the GameMaker's Testing Library. These are used to configure some of the library and its behavior.
You can find and change these definitions in the Libraries/GMTL/Setup/GMTL_definitions
script file inside the library. Here's the table of definitions you can edit in that file:
Name | Description | Default Value |
---|---|---|
gmtl_run_at_start | Run GMTL tests at game start. | true |
gmtl_wait_frames_before_start | Frames to wait before start running GMTL suites. | 10 |
Here you will find all the functions you need to start writing tests with the GameMaker's Testing Library. These are some of functions to create your tests: suite
, section
, and test
. Here's an example of how to use them:
suite(function() {
section("My Section", function() {
test("My Test", function() {
// Test code here
});
});
});
suite(callback)
Important
You must always start your tests with a suite
function. This is the root of your test suite and will contain all your tests. If you don't start with a suite
, your tests will not run and probably throw an error.
Suites are used to group sections of tests together. They can be nested to create a hierarchy of tests. Suites can contain other sections and tests. You can put a suite in any script file, but it is recommended to have a single suite per script file.
describe(name, callback)
or section(name, callback)
Important
describe
and section
are the same function. You can use either of them to group your tests together. They are used to create a new section of tests inside a suite. You cannot nest sections inside other sections. sections should always be inside a suite and outside test.
Sections are used to group tests together. They can contain tests but not other sections nor suites. You can put a section in any suite and it is recommended to have multiple sections per suite to group your tests together.
test(name, callback)
or it(name, callback)
Important
test
and it
are the same function. You can use either of them to create a new test. They are used to create a new test inside a section. You cannot nest tests inside other tests. Tests should always be inside a section.
Tests are used to test a specific piece of code. They should be small and focused on a single aspect of your code. You can put a test in any section and it is recommended to have multiple tests per section to test different parts of your code.
Inside a test, you can use the expect
function to make assertions about your code. This function will compare the actual value with the expected value and throw an error if they are not the same as the one expected using a matcher. You can look at the Common Matchers section to see various of the available matchers.
each(name, callback, cases)
The each
function is used to run a test multiple times with different arguments. This is useful when you want to test the same code with different inputs. You can pass an array of arguments to the each
function and it will run the test for each argument.
The name of the test can be customized by using {0}, {1}, {2}, ...
in the name string. These will be replaced by the arguments passed to the each
function. And it will add a [Case {index}]
to the test name.
It's basically works like a loop that runs the test for each argument in the array. You can also add arrays inside the main array to test multiple arguments at once.
Example:
suite(function() {
section("My Section", function() {
each("Should {0} + {1} be {2}.", function(_arg1, _arg2, _arg3) {
expect(_arg1 + _arg2).toBe(_arg3);
},
[
[1, 1, 2],
[5, 5, 10],
[3, 6, 9],
[-5, 5, 0]
]);
});
});
skip(name, callback, [cases])
The skip
function is used to skip a test or a section of tests. This is useful when you want to temporarily disable a test without deleting it. You can pass a test or a section to the skip
function and it will not run the test when the suite is executed.
Example:
suite(function() {
section("My Section", function() {
test("My Test", function() {
// Test code here
});
skip("My Skipped Test", function() {
// Test code here
});
});
});
expect(actual)
The expect
function is used to make assertions about your code. It will compare the actual value with the expected value and throw an error if they are not the same. You can use various matchers to make different types of assertions. You can look at the Common Matchers section to see various of the available matchers.
You can also use the method .never()
to negate the assertion. This is useful when you want to check if something never happens. You can look at the never section to see how to use it.
Example:
suite(function() {
section("My Section", function() {
test("My Test", function() {
expect(1 + 1).toBe(2);
expect(1 + 1).never().toBe(3);
});
});
});
Here you will find all the functions you need to clean up your tests with the GameMaker's Testing Library. These are some of functions to clean up your tests: beforeEach
, afterEach
, beforeAll
, and afterAll
. Here's an example of how to use them:
beforeAll(function() {
// Code to run before all tests
});
beforeEach(function() {
// Code to run before each test
});
afterEach(function() {
// Code to run after each test
});
afterAll(function() {
// Code to run after all tests
});
suite(function() {
section("My Section", function() {
test("My Test", function() {
// Test code here
});
});
});
The order of execution of the teardown functions is as follows:
> Suite starts
> Start describe/section
> Run beforeAll()
> Start loop of it/test
> Run beforeEach()
> Run it/test
> Run afterEach()
> Finish loop of it/test
> Run afterAll()
> Finish describe/section
> Suite ends
So, the beforeAll
function will run before all tests in the suite, the beforeEach
function will run before each test, the afterEach
function will run after each test, and the afterAll
function will run after all tests in the suite.
These functions should be defined inside a suite
or a section
but never inside a test
.
Note
The before*
and after*
functions are optional and you don't need to use them if you don't need to run code before or after all tests in a suite.
Warning
Variables inside the before*
and after*
functions are not accessible inside the tests. If you need to share data between the tests and the before*
and after*
functions, you can use global variables or the self
object. But beware since there are reserved words that you can't use as global variables.
beforeEach(callback)
The beforeEach
function is used to run a piece of code before each test in a section. This is useful when you want to set up some data before each test. You can put a beforeEach
function in any section and it will run before each test in that section.
afterEach(callback)
The afterEach
function is used to run a piece of code after each test in a section. This is useful when you want to clean up some data after each test. You can put an afterEach
function in any section and it will run after each test in that section.
beforeAll(callback)
The beforeAll
function is used to run a piece of code before all tests in a suite. This is useful when you want to set up some data before all tests. You can put a beforeAll
function in any suite and it will run before all sections in that suite. You can also put a beforeAll
function in a section and it will run before all tests in that section.
afterAll(callback)
The afterAll
function is used to run a piece of code after all tests in a suite. This is useful when you want to clean up some data after all tests. You can put an afterAll
function in any suite and it will run after all sections in that suite. You can also put an afterAll
function in a section and it will run after all tests in that section.
Here you will find all the matchers you can use after the expect
function to make assertions about your code. Some matchers are type-specific and can only be used with certain types of values. You can find an example on how to use every matcher in the /Demo/GMTL_demo_tests
script inside this library.
toBe(expected)
The toBe
matcher is used to compare the actual value with the expected value using the ==
operator. This matcher will check if the actual value is the same as the expected value. It will throw an error if they are not the same. This matcher is used to compare primitive values like numbers, strings, ref index, and booleans, and can accept arrays, but not structs. For structs, you can use the toBeEqual
matcher.
toBeEqual(expected)
The toBeEqual
matcher is used to compare the actual value with the expected value using the ==
operator. This matcher will check if the actual value is the same as the expected value. It will throw an error if they are not the same. This matcher is used to compare primitive values like numbers, strings, ref index, and booleans, and can accept arrays and structs.
toContain(expected)
The toContain
matcher is used to check if the actual value contains the expected value. This matcher will check if the actual value is an array and contains the expected value. It will throw an error if the actual value is not an array or struct, or if it does not contain the expected value.
toHaveLength(expected)
The toHaveLength
matcher is used to check if the actual value has the expected length. This matcher will check if the actual value is an array, string or struct and has the expected length. It will throw an error if the actual value is not an array, string or struct, or if it does not have the expected length.
toHaveProperty(property, [value])
The toHaveProperty
matcher is used to check if the actual value has the expected property. This matcher will check if the actual value is a struct and has the expected property. It will throw an error if the actual value is not a struct, or if it does not have the expected property. You can also pass a value to check if the property has the expected value.
toHaveReturned()
The toHaveReturned
matcher is used to check if the actual value has returned a value. This matcher will check if the actual value is a function and has returned a value. It will throw an error if the actual value is not a function, or if it has not returned a value. (not undefined
)
toHaveReturnedWith(expected)
The toHaveReturnedWith
matcher is used to check if the actual value has returned the expected value. This matcher will check if the actual value is a function and has returned the expected value. It will throw an error if the actual value is not a function, or if it has not returned the expected value.
Here you will find all the matchers you can use to check the truthiness of a value. These matchers are used to check if a value is true
or false
.
toBeTruthy()
The toBeTruthy
matcher is used to check if the actual value is true
. This matcher will check if the actual value is true
. It will throw an error if the actual value is not true
.
toBeFalsy()
The toBeFalsy
matcher is used to check if the actual value is false
. This matcher will check if the actual value is false
. It will throw an error if the actual value is not false
.
Here you will find all the matchers you can use to compare numbers. These matchers are used to compare numbers and check if they are greater than, less than, or equal to other numbers.
toBeGreaterThan(expected)
The toBeGreaterThan
matcher is used to check if the actual value is greater than the expected value. This matcher will check if the actual value is greater than the expected value. It will throw an error if the actual value is not greater than the expected value.
toBeLessThan(expected)
The toBeLessThan
matcher is used to check if the actual value is less than the expected value. This matcher will check if the actual value is less than the expected value. It will throw an error if the actual value is not less than the expected value.
toBeGreaterThanOrEqual(expected)
The toBeGreaterThanOrEqual
matcher is used to check if the actual value is greater than or equal to the expected value. This matcher will check if the actual value is greater than or equal to the expected value. It will throw an error if the actual value is not greater than or equal to the expected value.
toBeLessThanOrEqual(expected)
The toBeLessThanOrEqual
matcher is used to check if the actual value is less than or equal to the expected value. This matcher will check if the actual value is less than or equal to the expected value. It will throw an error if the actual value is not less than or equal to the expected value.
.never()
![IMPORTANT] The
never
matcher is used to negate an assertion. This matcher is used to check if something never happens. You can use it after theexpect
function to negate the assertion. It basically works like anot
operator in other testing libraries, butnot
cannot be used in GameMaker because is a reserved word.
Here you will find all the matchers you can use to negate an assertion. These matchers are used to check if something never happens.
Example:
suite(function() {
section("My Section", function() {
test("My Test", function() {
expect(1 + 1).toBe(2);
expect(1 + 1).never().toBe(3);
});
});
});
Here you will find all the functions you can use to simulate events in your tests. These functions are used to simulate key presses, mouse clicks, gamepad button presses, and other events. You can use these functions to test how your code reacts to different events.
create(x, y, object, [params])
The create
function is used to create an instance of an object at a specific position. This function will create an instance of the object at the specified position. You can also pass additional parameters to the object's Create
event. The instance id of the created object will be returned and should be deleted after the test using instance_destroy()
.
Example:
suite(function() {
section("My Section", function() {
test("My Test", function() {
var _obj = create(0, 0, obj_player);
expect(_obj).toBeGreaterThan(-1);
instance_destroy(_obj);
});
});
});
simulateKeyPress(key)
The simulateKeyPress
function is used to simulate a key press event. This function will simulate a key press event for the specified key. You can pass a virtual key code to the function to simulate a key press event. The key code should be a virtual key code like vk_space
, vk_left
, vk_right
, etc.
simulateKeyRelease(key)
The simulateKeyRelease
function is used to simulate a key release event. This function will simulate a key release event for the specified key. You can pass a virtual key code to the function to simulate a key release event. The key code should be a virtual key code like vk_space
, vk_left
, vk_right
, etc.
simulateKeyHold(key)
The simulateKeyHold
function is used to simulate a key hold event. This function will simulate a key hold event for the specified key. You can pass a virtual key code to the function to simulate a key hold event. The key code should be a virtual key code like vk_space
, vk_left
, vk_right
, etc. The key will be held until a simulateKeyRelease
function is called.
simulateGamepadButtonPress(device, button)
The simulateGamepadButtonPress
function is used to simulate a gamepad button press event. This function will simulate a gamepad button press event for the specified device and button. You can pass a device id and a button id to the function to simulate a gamepad button press event. The device id should be a device id like 0
, 1
, etc. The button id should be a button id like gp_face1
, gp_*
, etc.
simulateGamepadButtonRelease(device, button)
The simulateGamepadButtonRelease
function is used to simulate a gamepad button release event. This function will simulate a gamepad button release event for the specified device and button. You can pass a device id and a button id to the function to simulate a gamepad button release event. The device id should be a device id like 0
, 1
, etc. The button id should be a button id like gp_face1
, gp_*
, etc.
simulateGamepadButtonHold(device, button)
The simulateGamepadButtonHold
function is used to simulate a gamepad button hold event. This function will simulate a gamepad button hold event for the specified device and button. You can pass a device id and a button id to the function to simulate a gamepad button hold event. The device id should be a device id like 0
, 1
, etc. The button id should be a button id like gp_face1
, gp_*
, etc. The button will be held until a simulateGamepadButtonRelease
function is called.
simulateMouseClickPress(button, [x], [y])
The simulateMouseClickPress
function is used to simulate a mouse click press event. This function will simulate a mouse click press event for the specified button. You can pass a button id to the function to simulate a mouse click press event. The button id should be a button id like mb_left
, mb_right
, etc. You can also pass an optional x and y position to simulate a mouse click at a specific position.
simulateMouseClickRelease(button, [x], [y])
The simulateMouseClickRelease
function is used to simulate a mouse click release event. This function will simulate a mouse click release event for the specified button. You can pass a button id to the function to simulate a mouse click release event. The button id should be a button id like mb_left
, mb_right
, etc. You can also pass an optional x and y position to simulate a mouse click at a specific position.
simulateMouseClickHold(button, [x], [y])
The simulateMouseClickHold
function is used to simulate a mouse click hold event. This function will simulate a mouse click hold event for the specified button. You can pass a button id to the function to simulate a mouse click hold event. The button id should be a button id like mb_left
, mb_right
, etc. You can also pass an optional x and y position to simulate a mouse click at a specific position. The button will be held until a simulateMouseClickRelease
function is called.
simulateMousePosition(x, y)
The simulateMousePosition
function is used to simulate a mouse position event. This function will simulate a mouse position event for the specified position. You can pass an x and y position to the function to simulate a mouse position event. The mouse position will be set to the specified position.
simulateFrameWait([frames])
Important
This function simulates frames passing by executing the step events of the objects, the frames are not actually rendered by GameMaker.
The simulateFrameWait
function is used to simulate a frame wait event. This function will wait for the specified number of virtual frames before continuing. You can pass an optional number of frames to the function to wait for a specific number of frames. If no frames are specified, it will wait for one frame.
simulateEvent(event_type, event_number, [instance_id])
The simulateEvent
function is used to simulate an event for an object. This function will simulate an event for the specified object. You can pass an object id, an event id, and an optional instance id to the function to simulate an event for the specified object. The event type and number should be theones described in the manual like ev_create
, ev_step
, etc. The instance id should be an instance id, if no instance id is specified, it will simulate the event for all instances currently active.
simulateTimesource(parent, period, unit, callback, [args], [repetitions], [expiry])
The simulateTimesource
function is used to simulate a timesource. This function takes the exact same parameters than a GameMaker native timesource, but it will not actually create a timesource, it will just virtually simulate the event. This is useful when you want to test pseudo-async events like a custom garbage collector or waiting some frames for an event to happen.
This function creates a constructor that will be used to simulate the timesource and has 2 methods to call for it to work: .start()
that mimics the behaviour of time_source_start(), and .stop()
that mimics the behaviour of time_source_stop().
If you want to strictly call the GameMaker's built-in functions you can use original_time_source_create()
, original_time_source_start()
, etc
Note
Since the original GameMaker's call_later()
function works behind the scenes with a timesource, this function is basically a wrapper for the simulateTimesource
function too.
simulateCallLater(callback, [args], [repetitions], [loop])
The simulateCallLater
function is used to simulate a call_later() event. This function will simulate a call later event for the specified callback. You can pass a callback, an optional array of arguments, an optional number of repetitions, and an optional loop flag to the function to simulate a call later event. The callback will be called after the specified number of frames.
If you want to strictly call the GameMaker's built-in function you can use original_call_later()
directly in your code.