with one click
direct-tests
// Write and run fast direct mode tests for GenLayer intelligent contracts.
// Write and run fast direct mode tests for GenLayer intelligent contracts.
Use the GenLayer CLI to deploy, interact with, and debug intelligent contracts.
Validate GenLayer intelligent contracts with the GenVM linter.
Write and run integration tests against a GenLayer environment.
Write production-quality GenLayer intelligent contracts. Always pins concrete GenVM runner version hashes and never uses local-only test/latest runner aliases. Covers equivalence principles, storage rules, LLM resilience, and cross-contract interaction.
Interactive wizard to set up a GenLayer validator node on Linux.
Manage GenLayer validators across testnets using the genlayer CLI. Join, fund, set identity, list, and organize validators per network and owner.
| name | direct-tests |
| description | Write and run fast direct mode tests for GenLayer intelligent contracts. |
| allowed-tools | ["Bash","Read","Write","Edit"] |
Write fast, in-memory tests for intelligent contracts. No server, no Docker ā tests run in ~30-50ms.
pytest tests/direct/ -v
pytest tests/direct/test_specific.py -v
pytest tests/direct/test_specific.py::test_one_case -v
Available from genlayer-test pytest plugin:
def test_example(direct_vm, direct_deploy, direct_alice, direct_bob):
# direct_vm ā VMContext with cheatcodes
# direct_deploy ā deploy a contract file
# direct_alice ā test address
# direct_bob ā test address
pass
All fixtures: direct_vm, direct_deploy, direct_alice, direct_bob, direct_charlie, direct_owner, direct_accounts
def test_set_and_get(direct_vm, direct_deploy, direct_alice):
contract = direct_deploy("contracts/my_contract.py")
direct_vm.sender = direct_alice
contract.set_data("hello")
result = contract.get_data(direct_alice)
assert result == "hello"
For contracts that call gl.nondet.web.get():
import json
def test_with_web_mock(direct_vm, direct_deploy, direct_alice):
contract = direct_deploy("contracts/my_contract.py")
direct_vm.sender = direct_alice
# Pattern: regex matching on URL
direct_vm.mock_web(
r".*api\.example\.com/prices.*",
{"status": 200, "body": '{"price": 42.5}'},
)
contract.update_price("ETH/USD")
assert contract.get_price("ETH/USD") == 42.5
direct_vm.mock_web(
r"api\.example\.com/data",
{
"response": {
"status": 200,
"headers": {},
"body": json.dumps({"key": "value"}).encode()
},
"method": "GET"
}
)
For contracts that call gl.nondet.exec_prompt():
direct_vm.mock_llm(
r".*Extract the match result.*", # Regex on prompt text
json.dumps({"score": "2:1", "winner": 1}),
)
direct_vm.clear_mocks() # Reset between test scenarios
# Set transaction sender
direct_vm.sender = direct_alice
# Set native value (wei)
direct_vm.value = 1000000000000000000 # 1 ETH
# Expect a revert
with direct_vm.expect_revert("Insufficient balance"):
contract.withdraw(1000)
# Temporary sender change
with direct_vm.prank(direct_bob):
contract.method() # Called as bob
# Snapshot and restore state
snap_id = direct_vm.snapshot()
contract.modify_state()
direct_vm.revert(snap_id) # State restored
# Set account balance
direct_vm.deal(direct_alice, 1000000000000000000)
# Time travel
direct_vm.warp("2024-06-01T12:00:00Z")
tests/direct/
āāā conftest.py # Shared fixtures and mock helpers
āāā test_<feature>.py # Tests per feature/method
āāā test_<feature>_web.py # Tests requiring web/LLM mocks
| Category | Example |
|---|---|
| State transitions | Create ā read back ā verify fields |
| Validation / reverts | Invalid inputs, unauthorized callers |
| Access control | Owner-only methods, role checks |
| Edge cases | Empty state, boundary values, overflow |
| Web/LLM parsing | Mock responses ā verify extraction logic |
def test_only_owner(direct_vm, direct_deploy, direct_alice, direct_bob):
contract = direct_deploy("contracts/my_contract.py")
direct_vm.sender = direct_alice
contract.create_item("item_1")
direct_vm.sender = direct_bob
with direct_vm.expect_revert("Only owner"):
contract.delete_item("item_1")
def test_state_flow(direct_vm, direct_deploy, direct_alice):
contract = direct_deploy("contracts/my_contract.py")
direct_vm.sender = direct_alice
contract.create_item("item_1")
assert contract.get_item("item_1")["status"] == "pending"
contract.approve_item("item_1")
assert contract.get_item("item_1")["status"] == "approved"
import json
def mock_price_api(direct_vm, pair: str, price: float):
"""Mock a price API response."""
direct_vm.mock_web(
rf".*api\.example\.com/prices/{pair}.*",
{"status": 200, "body": json.dumps({"price": price})},
)
direct_vm.sender = ... before calling write methods--json flag on genvm-lint check before writing tests to understand the contract's interface