A framework for test-driving assembly code for the Sinclair ZX Spectrum 48k.
The framework has been written with the Pasmo assembler. Simply grab the source in src
and include zx-spec.asm
to write tests:
include src/zx-spec.asm
spec_init
describe 'ld a,n'
it 'sets A register to value'
ld a,5
assert_a_equal 5
spec_end
You can optionally name a set of asserts using the it
macro. This groups the asserts into a single test. In addition to it
, you can use the describe
macro to group one or more tests. Nested describe
or it
macros are not permitted.
By default test descriptions are not output for tests that pass. You can output test descriptions even for passing tests by defining zxspec_config_verbose_output
as non-zero either on the command-line of Pasmo (--equ zxspec_config_verbose_output
), or in code before you call spec_init
:
zxspec_config_verbose_output equ $FF
This can be used to generate a form of living documentation for your project.
By default, expected and actual values are displayed as decimals. You can switch to hexadecimal by defining zxspec_config_display_numbers_as_hex
as non-zero either on the command-line of Pasmo (--equ zxspec_config_display_numbers_as_hex
), or in code before you call spec_init
:
zxspec_config_display_numbers_as_hex equ $FF
See test/test-hex.asm for example usage. Note that assert_bytes_equal
always displays expected/actual bytes as a comma-seperated list of hexadecimal pairs, regardless of this setting.
See test/test-passes.asm for examples.
You can immediately pass or fail a test by using:
assert_pass
assert_fail
These assertions will preserve register values.
assert_a_equal
assert_a_not_equal
assert_b_equal
assert_b_not_equal
assert_c_equal
assert_c_not_equal
assert_d_equal
assert_d_not_equal
assert_e_equal
assert_e_not_equal
assert_h_equal
assert_h_not_equal
assert_l_equal
assert_l_not_equal
assert_a_is_zero
assert_a_is_not_zero
assert_bc_equal
assert_bc_not_equal
assert_de_equal
assert_de_not_equal
assert_hl_equal
assert_hl_not_equal
assert_ix_equal
assert_ix_not_equal
Asserting on the IY register value is not currently supported. The IY register is used by Spectrum ROM routines as a index to system variables and is not generally recommended to be used in custom routines due to the added complexity of ensuring its use does not interfere with normal operation.
assert_z_set
assert_z_reset
assert_carry_set
assert_carry_reset
assert_s_set
assert_s_reset
assert_p_v_set
assert_p_v_reset
Be warned that these assertions will not preserve register values.
assert_byte_equal
assert_byte_not_equal
assert_word_equal
assert_word_not_equal
assert_str_equal
assert_str_not_equal
assert_bytes_equal
assert_bytes_not_equal
-
Python 2.7 (for running ZX Spec tests)
-
Docker (for running Pasmo)
-
Fuse Emulator
Linux
$ sudo apt-get install fuse-emulator-common spectrum-roms
macOS
$ brew install homebrew/games/fuse-emulator
You can also run Fuse with Docker by setting the
FUSE
environment variable accordingly:$ export "FUSE=docker run -v /tmp/.X11-unix:/tmp/.X11-unix --privileged -e DISPLAY=unix$DISPLAY -it rhargreaves/fuse-emulator"
ZX Spec can be tested by running:
$ make test
Two sets of automated tests will run. One set results in all tests passing, and the other set results in all tests failing. The results are sent to an emulated ZX Printer (rather than sent to the display) which is then output by the emulator to a text file. This file is then validated to ensure the framework is working correctly.
Unfortunately, the speed of the ZX Printer is also emulated resulting in the tests taking a few minutes to complete. I don't currently know of a way to speed this up!
You can run a couple of example demos:
$ make demo-green
$ make demo-red
$ make demo-mix
I had a go at completing part of the Checkout Kata using this framework.
- This project was inspired by 64spec - a Commodore 64 Testing Framework