Skip to content

agglayer/e2e

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AggLayer End to End Tests

The TLDR for getting started is that these tests are based on a TAP compatible tool called Bats. All of the tests are small bash scripts. If the test exits with a non-zero exit code, the test fails. If you’re new to bash or Bats, these are some useful links.

How to run your test

There are two easy ways to run your test cases. The easiest way is to execute the ./test-runner.sh script. That script has several conveniences that will be important for test automation. If you’d like to run a single test file, or use Bats directly, it’s pretty easy as well:

# You'll want to set whatever environment variables your test needs. If you want to use defaults you could skip this.
set -a
source tests/.env
set +a

# Some tests will use helpers. If your test does, you'll want to add that to the bats lib path.
export BATS_LIB_PATH="$PWD/core/helpers/lib"

# Now you can run bats
bats tests/agglayer/bridges.bats --filter-tags agglayer,rpc

Philosophy and Goals

Separation of concerns between infrastructure and test logic is a major goal of this project. We want to have a wide variety of tests. The tests themselves shouldn’t be concerned with the details of the infrastructure on which the execute. A single test should be configurable based on environment variables and should be able to run against a Kurtosis devnet or a mainnet RPC.

Ideally this repository is self documenting. For our test cases, that means they should be thoughtfully named and tagged. In the case of a failure, the error messaging and naming should be it very clear what failed and what it might mean.

# Bad example
@test "send bridge" {
    if ! bridge ; then {
        echo "bridge failed"
        exit 1
    }
}

# Better example
@test "bridge native eth from l1 to l2" {
    if ! bridge ; then {
        echo "Bridge deposit was not claimed despite being finalized on L1. Check that bridge service is running properly"
        exit 1
    }
}

The “better” example above has a descriptive name that indicates what type of bridge is being tested. It also has a lot more context if and when there is a failure.

Another major goal of this project is to have a simple developer experience. Making that happen isn’t easy, but we want to have shared environment variables that are common across test cases. Similarly, we want to have tags and a project layout that’s intuitive.

Thinking about environment variables

As a test developer, you can define whatever environment variables you like, but in order for the test cases to be executed via generic automations, it’s critical that you’re aware of commonly used environment variables and to use them whenever possible.

VariablePurpose
RPC_URLA generic JSON RPC URL for tests that do not require L1/L2 context
L1_RPC_URLAn RPC URL that serves as the L1 for some rollup or validium
L2_RPC_URLAn RPC URL for a rollup that’s anchored on L1
PRIVATE_KEYA private key that’s funded for RPC_URL
L1_PRIVATE_KEYA private key that’s funded for L1_RPC_URL
L2_PRIVATE_KEYA private key that’s funded for L2_RPC_URL
SEQUENCER_RPC_URLAn RPC URL that’s directly connected to a sequencer
GAS_TOKEN_ADDRThe L1 address of a custom gas token
BRIDGE_SERVICE_URLThe URL of the bridge service used for claiming deposits
L1_BRIDGE_ADDRThe address of the bridge on L1
L2_BRIDGE_ADDRThe address of the bridge on L2

A few points on the design and thinking. In general, we’re going to prefer deriving rather than specifying everything. Rather than specifying an L1_ETH_ADDRESS variable that can be set, we would derive this value from the L1_PRIVATE_KEY. Similarly, rather than specifying the ~networkID~ with something like L2_NETWORK_ID, we would rather read this value from the bridge.

The test cases aren’t meant for a specific environment, but in many cases the default values for environment variables will target the kurtosis-cdk package or the kurtosis-polygon-pos package. For example, if you startup the kurtosis package like this:

kurtosis run --enclave cdk --args-file .github/tests/combinations/fork12-cdk-erigon-sovereign.yml .

Many tests will assume the default target of the test is kurtosis and define the keys and URLs accordingly.

Test Case Naming

Consistent and clear test naming is critical for maintaining readability, ensuring searchability, and improving test result clarity. We will enforce these naming standards during code review to maintain consistency across our test suite. Naming Standard

Each test should follow this pattern:

@test "<action> <test scope> <conditions or properties> [expected outcome]"

Where:

  • <action> – What the test is doing (e.g., bridge, send, claim, create).
  • <test scope> – The subject of the test (e.g., native ETH, ERC20, contract, RPC call).
  • <conditions or properties> (optional) – Any constraints or test conditions (e.g., with low gas, after).
  • [expected outcome] (only if needed) – If success/failure isn’t obvious (e.g., fails if contract is paused).

Examples:

  • @test "bridge native ETH from L2 to L1"
  • @test "bridge native ETH from L2 to L1 without initial deposit fails"
  • @test "withdraw ERC20 and finalize after challenge period"
  • @test "deposit ETH on L2 with custom gas limit"
  • @test "replay transaction on L1 with same nonce reverts"
  • @test "bridge fails when contract is paused"
  • @test "query interop_getLatestSettledCertificateHeader on agglayer RPC returns expected fields"

Best Practices:

  • Start with a clear action (e.g., bridge, deposit, send).
  • Be specific but concise—avoid vague test names.
  • Do not include “test” in the name (it’s redundant).
  • Use present tense (“bridge native ETH” not “bridging native ETH”).
  • Failure states should be explicit (e.g., “deposit fails when network ID is the current network”).

Test names should be reviewed for clarity and adherence to this standard before merging. Future linting may enforce a predefined set of allowed actions to further standardize test naming.

Project organization

TODO - This is still a work in progress. All of the tests live in the ./tests folder, but there isn’t a clear standard right now in terms of sub-folders, the names of files, how many cases should exist in a single file. Additionally, the standards for individual bats files are a bit arbitrary.

Thinking about tagging

TODO - Like the overall project organization, there’s more thinking needed for test tags. Each test probably needs a least two tags to be useful. E.g:

  • Target (i.e. what is being tested)
    • agglayer
    • lxly
    • erigon
    • evm
    • pos
    • heimdall
  • Type of test
    • regression
    • smoke
    • acceptance
    • stress
    • load

Common helper functions

TODO - We need to document the various helper functions. Some helpers might be mandatory (enforced by code review) while others are there for your convenience.