golden

package
v0.0.0-...-6b15219 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2023 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package golden is a package designed to make it possible to compare a game to a golden run for testing purposes. It takes a record saved in storage/filesystem format and compares it.

Typical Use

Typically you generate a new set of goldens by cd'ing into the package containing the game you want to test. Then you run `boardgame-util create-golden`, which generates a stub server for that game. As you play and create games, it will save the records as filesystem.record.Record, a format that is designed to be easy to read and modify as JSON. `create-golden` also will save a `golden_test.go` which will, when tests are run, compare the current GameManager's operation to the states and moves saved in the golden json blobs. These tests are a great way to verify that the behavior of your game does not accidentlaly change.

The format of filesystem.record.Record is optimized to be able to be hand-edited. It does a number of tricks to make sure that states and moves can be spliced in easily. First and foremost, it typically stores subsequent states not as full blobs but as diffs from the state before. This means that changing one state doesn't require also modifying all subsequent states to have the same values. The format also "relativizes" moves, setting their Version to -1, signifying that when fetched via record.Move(version), it should just use the version number it said it was. In addition, the Initiator field is stored as a relative number for how many moves back in history to go to. Finally, the Timestamp field is stored in a format that is as many seconds past the Unix epoch as the move is from the Game's Created timestamp. All of these properties mean that the format is (relatively) easy to tweak manually to add or remove moves.

You can also add a "Description" top-level field in the json to describe what the game is testing, which is useful to keep track of goldens that test various edge cases.

Remastering Goldens

Typically you record a golden, and then every time you test the game package, it will just verify the game logic still applies the same moves in the right order, with the right state modifications. But every so often you want to 'remaster' your golden. For example, perhaps the game logic has changed to have slightly different behavior, or you want to update the format of the golden to ensure it's canonical and up-to-date, to match changes in the underlying library.

It's possible to 'remaster' goldens, which means to re-record them and overwrite the original. You do this by passing true as the last value to Compare or CompareFolder. The `golden_test.go` that is generated for you will also automatically add a flag that will be passed in, so the canonical way to remaster is to run `go test -update-golden`, which instead of comparing the golden, will remaster it, overwriting the original.

After you remaster, it's a good idea to sanity check by doing a normal test (`go test`) to verify the game logic matches the new golden. You should also visually inspect the diff of the golden before commiting to make sure there aren't any unintended changes. The remastering process is designed to ensure that wherever possible content doesn't change. The design of filesystem.record.Record (described above) helps, but the remastering process also seeks to, for example, use existing timestamps wherever possible and generate reasonable intermediate timestamps for new moves that have been added.

If you have changed your game logic (for example, adding a new FixUp move that didn't exist before), then your old goldens will no longer match, so `go test` will fail, and you'll need to remaster your goldens. In the common case where the new FixUp move occurs within a run of already-existing FixUp moves, then you don't need to do anything special; `go test -update-golden`, combined with a manual sanity check of the diff, should be sufficient.

In the case where you have added a new Player move, or a move like SeatPlayer that occurs on its own, you'll need to do a bit of manual surgery. Before remastering, splice in a move record corresponding to the new move into the right place in the golden's Move section. Note that you'll need to update the Initiator fields of the single next move that comes in the immediate fixup run immediately after it, to verify that its relative value points to the new initator, so the new move is part of the run. You do not need to update the state patches to match, or the max Version of the Game section. Then, run `go test -update-golden` and verify the output looks correct. Note that your manual splice will now have been overwritten, which means that if the output was wrong, you'll need to reset it, manually modify again, and then remaster.

Index

Constants

View Source
const GameRecordsFolder = "testdata/golden"

GameRecordsFolder is the Path relative to package root where goldens should be stored

View Source
const GoldenTestFile = "golden_test.go"

GoldenTestFile is the name of the test file to create

Variables

This section is empty.

Functions

func CleanGoldenTest

func CleanGoldenTest(pkg *gamepkg.Pkg) error

CleanGoldenTest sees if GameRecordsFolder contains any tests. If it doesn't, removes that folder structure and golden_test.go

func Compare

func Compare(delegate boardgame.GameDelegate, recFilename string, updateOnDifferent bool) error

Compare is the primary method in the package. It takes a game delegate and a filename denoting a record to compare against. delegate shiould be a fresh delegate not yet affiliated with a manager. It compares every version and move in the history (ignoring things that shouldn't be the same, like timestamps) and reports the first place they divrge. Any time it finds a move not proposed by AdminPlayerIndex it will propose that move. As long as your game uses state.Rand() for all randomness and is otherwise deterministic then everything should work. If updateOnDifferent is true, instead of erroring, it will instead overwrite the existing golden with a new one. The boardgame-util create-goldens tool will output a test that will look for a `-update-golden` flag and pass in that variable here.

func CompareFolder

func CompareFolder(delegate boardgame.GameDelegate, recFolder string, updateOnDifferent bool) error

CompareFolder is like Compare, except it will iterate through any file in recFolder that ends in .json. Errors if any of those files cannot be parsed into recs. See Compare for more documentation.

func MakeGoldenTest

func MakeGoldenTest(pkg *gamepkg.Pkg) error

MakeGoldenTest ensures that GameRecordFolder exists and creates golden_test.go in the root of the package if it doesn't yet exist.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL