From sui-dev-agents
Writes Move tests for SUI contracts, including unit, integration, property-based, and gas benchmarks. Also covers Protocol 125 updates, replay with sender impersonation, and Move testing best practices.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sui-dev-agents:sui-testerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Complete testing solution for SUI Move contracts and frontend applications.**
Complete testing solution for SUI Move contracts and frontend applications.
This skill provides comprehensive testing across all layers:
Key changes affecting testing (June 2026):
sui move test --filter "regex_pattern" for precise test selection.sui::poseidon::poseidon_bn254.TxContext can be in any argument position. Update integration tests if they assume last-position TxContext.#[error] Annotation: Use #[error] on error constants for human-readable abort messages. Update #[expected_failure] tests to reference constant names, not hardcoded values.events field removed from simulateResult. Access events via effects.events() in dry-run tests.sui move test --gas-limit and update expected values.sui client object now shows decoded struct fields — useful for manual verification during integration tests.The new sui-fork tool plus sui replay --forking-mode lets you replay a historical transaction while impersonating an arbitrary sender — useful for reproducing user-reported bugs without their keys.
sui replay <tx-digest> \
--node https://graphql.devnet.sui.io/graphql \
--forking-mode impersonate \
--sender 0x<address>
Use this when an integration test needs to mimic real on-chain state under a specific signer.
# 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]
fun test_create_listing() {
let seller = @0xA;
let mut scenario = test_scenario::begin(seller);
// Create and verify listing
let listing = create_listing(nft, 1000, ctx);
assert!(price(&listing) == 1000, 0);
test_scenario::end(scenario);
}
Test cross-module interactions (marketplace + royalty).
// @check:skip
test('complete buy flow', async ({ page }) => {
await page.goto('http://localhost:5173');
await page.click('button:has-text("Connect Wallet")');
// ... complete user journey
});
#[test]
fun property_price_distribution() {
// Test invariant: total = seller + royalty + fee
let iterations = 100;
// ... verify invariant holds
}
sui move test --gas-profile
Target: >90% code coverage for core modules
sui move test --coverage
sui move coverage summary
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
analyze_source.py to get uncovered segments#[expected_failure] testsA. 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 */ }
❌ Not using test_scenario properly
test_scenario::next_tx between transactions, clean up with test_scenario::end❌ Testing with unrealistic gas budgets
--gas-limit flag❌ Ignoring test cleanup
#[expected_failure] for abort tests❌ Not testing error cases
assert! and abort paths with #[expected_failure(abort_code = X)]❌ Skipping property-based tests for math
❌ Not benchmarking gas costs
sui move test --gas-profile, track gas per operation❌ E2E tests without proper wallet setup
Test execution targets:
See reference.md for complete test patterns and examples.md for test examples. For installing the CLI, localnet setup, or faucet tokens, see the sui-install skill.
npx claudepluginhub first-mover-tw/sui-dev-agents --plugin sui-dev-agentsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.