Test Contracts
The Neo Solidity project uses a layered testing strategy that validates the compiler at every level: unit tests for individual components, integration tests for the pipeline, E2E compilation tests for real contracts, conformance tests against reference implementations, and Neo-Express smoke tests for on-chain deployment behavior.
Testing Philosophy
The test suite is organized in layers of increasing scope:
| Layer | What It Tests | Count | Command |
|---|---|---|---|
| Unit tests | Individual compiler components (lexer, parser, semantic, IR, codegen, runtime) | 400+ | cargo test --workspace |
| E2E compilation | Full pipeline from Solidity source to NEF + manifest | 74 tests | cargo test --test e2e_compilation_tests |
| Conformance | Output correctness against reference Neo implementations | 32 vectors | cargo test --test conformance_tests |
| Strict compatibility | Compilation of all devpack and example contracts | ~50 files | make test-compile-strict |
| Neo-Express smoke | Deploy + invoke on a real local Neo chain | 16+ scripts | make test-deploy-smoke-full |
| Tooling | TypeScript packages (Hardhat, Foundry, ABI router) | varies | make tooling-test |
| C# runtime | EVM-compatible runtime primitives | varies | make runtime-test |
Each layer catches different classes of bugs. Unit tests catch logic errors in individual passes. E2E tests catch integration issues between passes. Conformance tests catch behavioral divergence from Neo N3. Smoke tests catch deployment and invocation failures that only manifest on a real chain.
Quick Feedback Loop
During development, cargo test --workspace is the fastest way to validate changes. It runs all Rust tests (unit + integration + E2E + conformance) in under 30 seconds.
Quick Validation
For fast feedback during development:
# Run all Rust tests (unit + integration + E2E + conformance)
make test
# or equivalently:
cargo test --workspaceFor a quick compilation sanity check (verifies NEF magic bytes and manifest structure):
bash examples/test_compilation.shUnit Tests
Unit tests cover individual compiler components in isolation. They live in tests/ and inline #[cfg(test)] modules.
# Run all unit tests
cargo test --workspace
# Run tests for a specific module
cargo test lexer_tests
cargo test parser_tests
cargo test semantic_tests
cargo test runtime_tests
# Run with output visible (useful for debugging)
cargo test -- --nocapture
# Run a specific test by name
cargo test test_simple_storage_compilation
# Run tests in parallel (default) or single-threaded
cargo test -- --test-threads=1Runtime Tests
The embedded NeoVM runtime has extensive unit tests covering opcodes, syscalls, storage, iterators, and gas accounting:
# All runtime tests
cargo test runtime_
# Specific runtime areas
cargo test runtime_arithmetic
cargo test runtime_storage
cargo test runtime_cryptoE2E Compilation Tests
The E2E test suite compiles every example contract through the full pipeline and validates the output:
cargo test --test e2e_compilation_testsThis runs 74 tests that:
- Parse each Solidity source file
- Run it through the full compilation pipeline
- Verify the NEF is valid (magic bytes, checksum)
- Verify the manifest is valid JSON with correct ABI structure
- Check that method signatures match the Solidity source
To run with parallel threads for faster execution:
cargo test --test e2e_compilation_tests -- --test-threads=4Conformance Tests
Conformance tests compare compiler output against reference Neo N3 implementations:
cargo test --test conformance_testsThe suite includes 32 test vectors with a 93.8% pass rate. Each vector specifies:
- Input Solidity source
- Expected NeoVM opcodes or behavior
- Expected manifest structure
Failing conformance tests indicate behavioral divergence from the Neo N3 reference. These are tracked in docs/NEO_VM_PARITY_TODO.md.
Conformance Gaps
A 93.8% pass rate means some edge cases diverge from the Neo N3 reference. Check the parity TODO before relying on behavior covered by failing vectors.
Strict Compatibility Compilation Sweep
This sweep compiles all devpack libraries and example contracts with strict settings to catch regressions:
make test-compile-strict
# or:
bash examples/test_strict_compatibility_sweep.shThe sweep:
- Compiles every
.solfile indevpack/andexamples/new/ - Uses strict compiler flags
- Reports any unexpected warnings or errors
- Fails if
STRICT_SWEEP_FAIL_ON_UNEXPECTED_WARNINGS=1is set (used in CI)
Neo-Express Smoke Tests
Smoke tests deploy contracts to a real local Neo-Express chain and invoke methods to validate on-chain behavior. Each script is self-contained: it creates a fresh chain, deploys, invokes, and cleans up.
Prerequisites
- Neo-Express installed (see Installation)
jqandhexdumpavailableneo-solcbuilt (scripts auto-build if needed)
Individual Smoke Tests
# Basic deploy + invoke (storage, events, native calls)
make test-deploy-smoke
# Constructor arguments via _deploy(data, update)
make test-deploy-constructor-smoke
# Contract update lifecycle (deploy v1, update to v2)
make test-deploy-update-smoke
# Manifest permissions for native contracts (StdLib, CryptoLib)
make test-deploy-permissions-smoke
# abi.encode / abi.decode round-trip (StdLib.serialize/deserialize)
make test-deploy-encoding-smoke
# Revert reason propagation (abort message)
make test-deploy-abortmsg-smoke
# Low-level call (System.Contract.Call)
make test-deploy-lowlevel-call-smoke
# Low-level call failure handling
make test-deploy-lowlevel-call-failure-smoke
# External member-call dispatch
make test-deploy-external-call-smoke
# View/ReadOnly external calls
make test-deploy-view-readonly-call-smoke
# Compound assignment operators (+=, -=, etc.)
make test-deploy-compound-assignment-smoke
# Struct array element access
make test-deploy-struct-array-element-smoke
# Nested struct storage
make test-deploy-nested-struct-smoke
# Delete operator
make test-deploy-delete-smoke
# New showcase contracts (UpgradeLifecycle, WitnessGuard, OracleRelay)
make test-deploy-new-showcases-smokeRun All Smoke Tests
make test-deploy-smoke-fullThis runs all 16+ individual smoke tests sequentially. Each test is independent and creates its own temporary chain.
Famous DeFi Contract Smoke Tests
The repository also includes smoke tests for ports of iconic DeFi protocols:
# Wrapped GAS (WETH9-style)
make test-deploy-wgas-smoke
# Flash loan (Aave V2-style)
make test-deploy-flashloan-smoke
# AMM (Uniswap V2-style)
make test-deploy-amm-smoke
# Token vesting (OpenZeppelin-style)
make test-deploy-vesting-smoke
# Lending (Compound-style)
make test-deploy-lending-smoke
# DAO (Governor-style)
make test-deploy-dao-smoke
# All famous contract tests
make test-deploy-famous-allWhat Each Smoke Test Validates
The basic deploy smoke test (test_neoxp_deploy.sh) is representative of the pattern:
- Resolves
neo-solcbinary (builds if needed) - Resolves
neoxpbinary (installs if needed) - Creates a temporary working directory
- Writes a test contract inline
- Compiles with
neo-solc - Creates a fresh Neo-Express chain
- Transfers GAS to the deployer
- Deploys the contract
- Invokes
sender()and verifies it returns the deployer's script hash - Invokes
set(7)and verifies theValueSetevent fires - Invokes
get()and verifies it returns7 - Invokes
height()and verifies it returns an integer (tests native contract calls) - Cleans up the temporary directory
Workspace-Wide Test Suites
Core Tests
# Rust tests only
make test
# Rust tests + tooling tests + tooling lint
make test-all
# Rust tests + tooling tests + C# runtime tests
make test-all-fullTooling Tests
# TypeScript package tests (Hardhat, Foundry, ABI router, CLI tools)
make tooling-test
# TypeScript linting
make tooling-lintC# Runtime Tests
# Requires .NET SDK
make runtime-testCode Coverage
Generate coverage reports using cargo-tarpaulin:
# Install tarpaulin (one-time)
cargo install cargo-tarpaulin
# Generate HTML coverage report
make coverage
# Report is at coverage/tarpaulin-report.html
# Generate LCOV for CI
make coverage-ci
# Report is at coverage/lcov.info
# Check minimum coverage threshold (70%)
make check-coverageCI/CD Pipeline Setup
Recommended CI Sequence
The recommended CI pipeline runs these steps in order:
# 1. Code formatting check
cargo fmt --all -- --check
# 2. Linting
cargo clippy --all-targets --all-features -- -D warnings
# 3. Release build
cargo build --release
# 4. Full test suite
cargo test --workspace --all-features
# 5. E2E compilation tests (parallel)
cargo test --test e2e_compilation_tests -- --test-threads=4
# 6. Strict compatibility sweep
STRICT_SWEEP_FAIL_ON_UNEXPECTED_WARNINGS=1 make test-compile-strict
# 7. Neo-Express smoke tests (requires .NET)
make test-deploy-smoke-fullOne-Command CI Gate
The production-gate target runs all of the above:
make production-gateSee Production Readiness for details.
GitHub Actions Example
The repository's CI workflow (.github/workflows/ci.yml) includes:
- Standard Rust CI (fmt, clippy, test) on Ubuntu
- E2E compilation tests
- A dedicated
neoxp-showcasesjob that:- Installs Rust + .NET 8 +
jq - Runs
examples/test_neoxp_new_showcases_smoke.sh - Validates
UpgradeLifecycleShowcase,WitnessGuardShowcase, andOracleRelayStrictShowcaseend-to-end
- Installs Rust + .NET 8 +
Writing Your Own Tests
Adding a Compilation Test
- Create a new Solidity file in
examples/orexamples/new/. - The E2E test suite automatically picks up files in these directories.
- Run
cargo test --test e2e_compilation_teststo verify.
Adding a Smoke Test
- Create a new script in
examples/following the pattern of existing scripts. - The script should:
- Create a temporary directory and clean up on exit
- Resolve
neo-solcandneoxpbinaries - Write a test contract inline
- Compile, deploy, invoke, and validate
- Add a Make target in the
Makefile. - Add the target to
test-deploy-smoke-fulldependencies.
Adding a Unit Test
Add #[test] functions in the relevant module or create a new test file in tests/:
#[test]
fn test_my_feature() {
let source = r#"
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Test {
function foo() public pure returns (uint256) {
return 42;
}
}
"#;
// Use the compiler API to compile and validate
// ...
}Test Summary
| Command | Scope | Duration | Requires |
|---|---|---|---|
cargo test --workspace | All Rust tests | ~30s | Rust |
cargo test --test e2e_compilation_tests | E2E compilation | ~10s | Rust |
cargo test --test conformance_tests | Conformance vectors | ~5s | Rust |
make test-compile-strict | Strict sweep | ~20s | Rust |
make test-deploy-smoke | Basic deploy | ~30s | Rust, .NET, jq |
make test-deploy-smoke-full | All smoke tests | ~5min | Rust, .NET, jq |
make test-all | Rust + tooling | ~1min | Rust, Node.js |
make production-gate | Everything | ~8min | Rust, Node.js, .NET, jq |
Related Pages
- Production Readiness -- Full pre-deployment gate.
- Compile Workflow -- CLI reference.
- Deploy Workflow -- Deployment patterns.
- Installation -- Set up the test environment.
