Skip to content

jigonr/statatest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

95 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

statatest

PyPI version Python versions License: MIT Tests codecov Documentation

A pytest-inspired testing and code coverage framework for Stata.

Documentation | GitHub | PyPI

Features

  • Test Discovery: Automatically find and run test_*.do files
  • Rich Assertions: Built on Stata's native assert with detailed failure messages
  • Fixture System: Reusable setup/teardown with pytest-like scoping
  • Code Coverage: Line-level coverage via SMCL comment instrumentation
  • CI Integration: JUnit XML output for GitHub Actions, LCOV for Codecov
  • Backward Compatible: Works with existing test patterns

Installation

Using uv (recommended)

# Install globally
uv tool install statatest

# Or run directly without installing
uvx statatest tests/

Using pip

pip install statatest

Quick Start

# Run all tests in tests/ directory
statatest tests/

# Run with coverage
statatest tests/ --coverage

# Generate JUnit XML for CI
statatest tests/ --junit-xml=junit.xml

Writing Tests

// tests/test_myfunction.do

// @marker: unit
program define test_basic_functionality
    // Setup
    clear
    set obs 10
    gen x = _n

    // Test
    myfunction x, gen(y)

    // Assert
    assert_var_exists y
    assert_equal _N, expected(10)
end

Assertions

Function Purpose Example
assert_equal Value equality assert_equal "\r(mean)'"", expected("5")`
assert_true Boolean true assert_true _N > 0
assert_false Boolean false assert_false missing(x)
assert_error Command should fail assert_error "invalid_command"
assert_var_exists Variable exists assert_var_exists myvar
assert_approx_equal Float comparison assert_approx_equal r(mean), expected(0.5) tol(0.01)

Fixtures

Create reusable setup/teardown functions with conftest.do:

// tests/conftest.do - Shared fixtures

program define fixture_sample_panel
    clear
    set obs 100
    gen int firm_id = ceil(_n / 10)
    gen int year = 2010 + mod(_n, 10)
    gen double revenue = exp(rnormal(15, 2))
end

program define fixture_sample_panel_teardown
    clear
end

Use fixtures in your tests:

// tests/test_analysis.do
// @uses_fixture: sample_panel

program define test_panel_analysis
    use_fixture sample_panel

    assert_obs_count 100
    assert_var_exists revenue
end

Built-in fixtures:

Fixture Purpose
fixture_tempfile Temporary file path ($fixture_tempfile_path)
fixture_empty_dataset Empty dataset with optional obs count
fixture_seed Reproducible random seed

Configuration

Create statatest.toml in your project root:

[tool.statatest]
testpaths = ["tests"]
test_files = ["test_*.do"]
stata_executable = "stata-mp"

[tool.statatest.coverage]
source = ["code/functions"]
omit = ["tests/*"]

[tool.statatest.reporting]
junit_xml = "junit.xml"
lcov = "coverage.lcov"

GitHub Actions Integration

name: Stata Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v5
      - run:
          uvx statatest tests/ --junit-xml=junit.xml --coverage
          --cov-report=lcov
      - uses: codecov/codecov-action@v5
        with:
          files: coverage.lcov

Requirements

  • Python: 3.11+
  • Stata: 16+

License

MIT License - see LICENSE for details.

Acknowledgments

  • Inspired by pytest
  • SMCL parsing patterns adapted from mcp-stata (AGPL-3.0)

About

Pytest-inspired testing and coverage framework for Stata

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors