Sui tester
Use when writing Move tests, setting up test suites, running gas benchmarks, or planning test strategy for SUI contracts. Triggers on "write tests", "test this module", "#[test]", "test coverage", "gas benchmark", "property-based test", or any Move testing task. Use even for simple "how do I test this function" questions.From its SKILL.md
npx -y skills add first-mover-tw/sui-dev-agents --skill sui-testerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.4 KB, as published. Nobody here has run it
SUI Tester
Complete testing solution for SUI Move contracts and frontend applications.
Overview
This skill provides comprehensive testing across all layers:
- Unit Tests - Test individual Move functions
- Integration Tests - Test module interactions
- E2E Tests - Test complete user journeys (frontend + contract)
- Property-Based Tests - Test invariants with random inputs
- Gas Benchmarks - Measure and track gas consumption
SUI Protocol 127 Testing Updates (shipped testnet v1.74.0; now mainnet v1.77.2 / P133)
Key changes affecting testing (June 2026):
- Move Linter (P128 / v1.74.1+):
sui move lintruns Move linters on the package. Lints also run insui move build/testby default —--no-lintto skip,--lintfor extra linters. Wire into CI alongsidesui move test. - gRPC
SimulateTransactiongasless tier (P127): now acceptsgas_price=0for gasless-tier-eligible transactions instead of erroring — useful for sponsored-tx dry runs. - Regex Test Filtering: Test filtering uses regex. Use
sui move test --filter "regex_pattern"for precise test selection. - poseidon_bn254: Available on all networks. Add tests for ZK-related functions using
sui::poseidon::poseidon_bn254. - TxContext Flexible Positioning:
TxContextcan be in any argument position. Update integration tests if they assume last-position TxContext. - gRPC Data Access: Integration tests must use gRPC client — JSON-RPC Quorum Driver is disabled and public-fullnode JSON-RPC is shut off (since 2026-07-31).
#[error]Annotation: Use#[error]on error constants for human-readable abort messages. Update#[expected_failure]tests to reference constant names, not hardcoded values.- GraphQL Simulation:
eventsfield removed fromsimulateResult. Access events viaeffects.events()in dry-run tests. - Gas Re-benchmarking: The New Move VM on testnet may produce different gas profiles compared to Protocol 118. If your tests assert specific gas values, re-run
sui move test --gas-limitand update expected values. - Decoded Object Inspection:
sui client objectnow shows decoded struct fields — useful for manual verification during integration tests.
Sender impersonation on a forked network (sui-fork + --skip-signing)
The sui-fork tool spins up a local network forked from mainnet/testnet/devnet state, then you submit transactions unsigned under any sender — useful for reproducing user-reported bugs without their keys. sui-fork is a separate crate in MystenLabs/sui (crates/sui-fork, subcommands start / status / advance-clock / advance-checkpoint); it's not shipped via suiup, build it with cargo build -p sui-fork.
# 1. Start a local fork from testnet state
sui-fork start --network testnet # optional: --checkpoint <n> --data-dir <path>
# 2. Point the CLI at the fork
sui client new-env --alias local-fork --rpc http://127.0.0.1:9000
sui client switch --env local-fork
# 3. Submit a tx as an impersonated sender, unsigned
sui client call --package <pkg> --module <mod> --function <fn> \
--sender 0x<address> \
--skip-signing # renamed from --forking-mode in v1.74.1
--skip-signing (a sui client tx flag, not a sui replay flag): "Submit the transaction without signatures for forked networks that support sender impersonation. Only intended for local forked-network testing." Use this when an integration test needs to mimic real on-chain state under a specific signer.
Quick Start
# Run all tests
sui move test
# Run with coverage
sui move test --coverage
# Generate coverage report
sui move coverage summary
# Run specific test (now uses regex!)
sui move test --filter "test_create_listing"
# Run all tests matching pattern
sui move test --filter "test_.*listing"
Test Types
Aim for a test pyramid — most coverage cheap and fast at the bottom, a few expensive checks at the top:
E2E Tests (5%)
/ \
Integration (15%)
/ \
Unit Tests (80%)
1. Move Unit Tests
#[test]
fun test_create_listing() {
let seller = @0xA;
let mut scenario = test_scenario::begin(seller);
// Reusable helpers keep setup DRY across tests
let nft = create_test_nft(&mut scenario);
let listing = create_listing(nft, 1000, scenario.ctx());
assert!(price(&listing) == 1000, 0);
assert!(seller(&listing) == seller, 1);
test_scenario::end(scenario);
}
2. Integration Tests
Test cross-module interactions (marketplace + royalty).
3. Frontend E2E Tests
// @check:skip
test('complete buy flow', async ({ page }) => {
await page.goto('http://localhost:5173');
await page.click('button:has-text("Connect Wallet")');
await page.click('button:has-text("Buy Now")');
await expect(page.locator('text=Purchase successful')).toBeVisible();
});
4. Property-Based Tests
#[test]
fun property_price_distribution() {
// Test invariant: total = seller + royalty + fee
let iterations = 100;
// ... verify invariant holds
}
5. Gas Benchmarks
sui move test --gas-profile
Test Coverage
Target: >90% code coverage for core modules
Quick Coverage Check
sui move test --coverage
sui move coverage summary
Automated Coverage Analysis Tools
This skill includes Python scripts in scripts/ for detailed coverage analysis:
# Location (relative to plugin install path)
SCRIPTS=<plugin_path>/skills/sui-tester/scripts
# Step 1: Run tests with coverage
cd /path/to/move/package
sui move test --coverage --trace
# Step 2: Source-level analysis (primary tool)
# Uses PTY to capture colored output, identifies exact uncovered segments
python3 $SCRIPTS/analyze_source.py -m <module_name>
python3 $SCRIPTS/analyze_source.py -m <module_name> -o coverage.md # Markdown report
python3 $SCRIPTS/analyze_source.py -m <module_name> --json # JSON output
# Step 3: LCOV statistics (function/line/branch breakdown)
sui move coverage lcov
python3 $SCRIPTS/analyze_lcov.py lcov.info -s sources/ --issues-only
# Step 4: Low-level bytecode analysis (optional)
sui move coverage bytecode --module <name> | python3 $SCRIPTS/parse_bytecode.py
# Step 5: Piped source analysis (alternative to analyze_source.py)
script -q /dev/null sui move coverage source --module <name> | python3 $SCRIPTS/parse_source.py
Coverage Improvement Workflow
- Analyze — Run
analyze_source.pyto get uncovered segments - Identify gaps:
- Uncalled functions → write tests that call them
- Uncovered assertions → write
#[expected_failure]tests - Untaken branches → write tests for both if/else paths
- Write tests for each gap (see patterns below)
- Verify — Re-run analysis to confirm improvement
- Repeat until >90% coverage
Coverage Test Patterns
A. Uncalled function:
#[test]
fun test_<function_name>() {
let mut ctx = tx_context::dummy();
<function_name>(&mut ctx);
// Assert expected behavior
}
B. Assertion failure path:
#[test]
#[expected_failure(abort_code = <ERROR_CONST>)]
fun test_<function>_fails_when_<condition>() {
let mut ctx = tx_context::dummy();
// Setup state that triggers the assertion failure
<function_call_that_should_fail>();
}
C. Branch coverage (if/else):
#[test]
fun test_<function>_when_true() { /* condition = true path */ }
#[test]
fun test_<function>_when_false() { /* condition = false path */ }
Common Mistakes
❌ Not using test_scenario properly
- Problem: Tests fail with "object not found" errors
- Fix: Always call
test_scenario::next_txbetween transactions, clean up withtest_scenario::end
❌ Testing with unrealistic gas budgets
- Problem: Tests pass but fail in production due to gas limits
- Fix: Set realistic gas budgets in tests, use
--gas-limitflag
❌ Ignoring test cleanup
- Problem: Objects leak between tests, intermittent failures
- Fix: Delete all created objects or use
#[expected_failure]for abort tests
❌ Not testing error cases
- Problem: Production failures from unexpected inputs
- Fix: Test all
assert!andabortpaths with#[expected_failure(abort_code = X)]
❌ Skipping property-based tests for math
- Problem: Edge cases cause overflow/underflow in production
- Fix: Test invariants with 100+ random inputs (prices, quantities, percentages)
❌ Not benchmarking gas costs
- Problem: Expensive operations drain user funds
- Fix: Run
sui move test --gas-profile, track gas per operation
❌ E2E tests without proper wallet setup
- Problem: Tests fail on wallet connection
- Fix: Use Playwright with wallet mock or testnet faucet automation
Configuration
Test execution targets:
- Unit tests: <30 seconds
- Integration tests: <2 minutes
- E2E tests: <10 minutes
- Full suite: <15 minutes
For installing the CLI, localnet setup, or faucet tokens, see the sui-install skill.