Test data and fixtures

After creating a project with:

goat init ./my-project \
  --name my-project \
  --git-repo git@github.com:your-user/my-project.git \
  --terminal-prefix MYAPP \
  --default-language en \
  --supported-languages en,pl \
  --template goatcms

you receive not only the application structure, but also sample data and documents matched to the current version of Goat.

This allows you to start the project immediately and see a working application with sample content, without having to manually prepare initial data.

Fixtures therefore serve two purposes:

  • they provide the data needed for local development and testing,
  • they create sample documentation compatible with the version of the generator you are currently using.

This is particularly useful when updating a project. Documentation and examples can be versioned together with the code, making it easier to verify how a specific version of the application works.

Main project fixture

The logic responsible for loading data is located in:

herd/fixture.goat

The script can create or update, among other things:

  • documents,
  • sample data,
  • records required by the application,
  • demo content,
  • data needed during local development.

herd/fixture.goat is executed when starting the development environment through:

herd/dev.goat

As a result, after starting the project, the local application can automatically receive the data set needed to operate.

The fixture can also be run manually.

Documentation as application data

Sample documentation is stored in Markdown files.

The default structure looks as follows:

herd/fixtures/doc/<ver>/<lang>/<slug>.md

where:

  • <ver> specifies the documentation version,
  • <lang> specifies the language,
  • <slug> is a stable document identifier.

Example:

herd/fixtures/doc/v1/pl/architektura.md

This approach makes it possible to store documentation as regular text files alongside the project.

You can:

  • version them in Git,
  • review them in code review,
  • edit them in any editor,
  • modify them with AI,
  • translate them,
  • reload them into the application.

Documentation therefore remains part of the project's source code rather than content that exists exclusively in the database.

Loading Markdown documents

Markdown files are loaded by:

herd/fixture.goat

using the command:

crud:doc:persist

Example:

crud:doc:persist \
  --lang=pl \
  --slug="moj-dokument" \
  --title="Mój dokument" \
  --description="Krótki opis dla wyszukiwarek i udostępnień." \
  --body-markdown-file="herd/fixtures/doc/v1/pl/moj-dokument.md"

The document content is retrieved directly from the file indicated by:

--body-markdown-file

Metadata such as the title, language, slug, or description is passed separately.

This makes it possible to separate the actual Markdown content from the information used by the application, SEO, or search mechanisms.

persist instead of creating duplicates

The command:

crud:doc:persist

is designed to be run multiple times.

Instead of creating a new record each time, it looks up an existing document by its identifier and updates it if it already exists.

This makes fixtures idempotent — running the same script multiple times should lead to the same expected data state instead of creating additional copies of the same records.

For entities inheriting from content, document identification is based on the pair:

lang + slug

For example:

pl + architektura
en + architecture

are treated as two different documents.

When updating existing content, maintain consistent lang and slug values.

Changing the slug may result in a new record being created instead of updating the existing one.

Stable slugs

A slug should be treated as a technical document identifier, not merely a simplified version of the title.

A good slug should be:

  • short,
  • stable,
  • written in lowercase,
  • free of special characters,
  • separated with hyphens.

Examples:

architecture
database
testing
model-and-generation

Do not change a slug merely because the document title has changed.

For example, a document:

slug: architektura

may later have the title:

Goat application architecture

without requiring its identifier to be changed.

This helps maintain stable URLs and correctly update records through persist.

Documentation versioning

The directory:

herd/fixtures/doc/<ver>/

makes it possible to store documentation assigned to a specific version of the project or generator.

This can be useful when subsequent versions of Goat change:

  • the project structure,
  • the model syntax,
  • available commands,
  • generator behavior,
  • the way the application is configured.

This allows users to work with documentation that matches the version of the code they actually have in front of them.

This is safer than relying solely on external documentation, which may describe a newer or older version of the tool.

Manually running fixtures

After building the application, a fixture can be loaded manually using the generated application's CLI:

myapp run:script --path=herd/fixture.goat

This is useful when:

  • you have changed the documentation,
  • you have added new sample data,
  • you want to refresh the local application state,
  • you are testing fixture behavior,
  • you do not want to restart the entire development environment.

Because the data is loaded using persist-type operations, rerunning the fixture should primarily update existing records rather than create duplicates.

Fixtures in everyday work

A typical workflow when editing documentation may look like this:

change to the Markdown file
        ↓
run herd/fixture.goat
        ↓
update the document in the database
        ↓
check the result in the application

For example:

vim herd/fixtures/doc/v1/pl/architektura.md

myapp run:script --path=herd/fixture.goat

You do not need to manually copy content into the database or edit records through the admin panel.

Fixtures and tests

Fixtures should create a predictable initial state.

Good test data is:

  • deterministic,
  • reloadable multiple times,
  • independent of production data,
  • insensitive to the order of manual operations,
  • sufficiently complete to run basic application scenarios.

Whenever possible, avoid generating random data if specific values are later used by tests.

Stable data makes the following easier:

  • E2E tests,
  • debugging,
  • reproducing bugs,
  • preparing an environment for a new developer,
  • comparing the behavior of subsequent application versions.

Sample data versus production data

Fixtures are intended primarily for development, testing, and demonstration environments.

Do not include:

  • real user data,
  • passwords,
  • tokens,
  • API keys,
  • secrets,
  • copies of production data containing confidential information.

Data stored in herd/fixtures/ should be treated as part of the repository, with the assumption that it may be available to anyone who has access to the project code.

Editorial guidelines for documentation

Each Markdown file should contain content in a single language.

Determine the document language by the directory structure and the parameter:

--lang

Keep slugs stable and do not make them dependent on minor title changes.

Store the title and description in the fixture:

--title="Mój dokument"
--description="Krótki opis dokumentu."

This ensures that metadata is stored together with the data definition and can be used, among other things, by:

  • SEO,
  • the search engine,
  • document lists,
  • content sharing,
  • future language versions.

Store the actual content in a separate Markdown file.

Documentation available from the first run

One of the advantages of fixtures provided by goat init is the ability to launch a project together with documentation corresponding to its version.

The workflow is simplified as follows:

goat init
    ↓
project generation
    ↓
environment startup
    ↓
fixture loading
    ↓
a ready-to-use application with documentation and sample data

As a result, a new project does not start with an empty application.

From the first run, you can see working examples, the data structure, and documentation prepared for the version of Goat being used.

This makes fixtures not only a mechanism for loading test data, but also an element of a self-documenting project.