# How to Perform Integration Testing with gltest in GenLayer

> Master integration testing in GenLayer with gltest. Deploy contracts locally, assert end-to-end behavior, and ensure seamless transaction and API interactions for robust smart contract development.

- Repository: [GenLayer Labs/genlayer-project-boilerplate](https://github.com/genlayerlabs/genlayer-project-boilerplate)
- Tags: how-to-guide
- Published: 2026-08-20

---

**Integration tests in GenLayer use the gltest framework to deploy smart contracts to a local Studio node and assert end-to-end behavior, ensuring that transactions, state changes, and external API interactions work correctly in a live environment.**

Integration testing with gltest in GenLayer validates the complete execution flow of smart contracts against a running GenLayer Studio instance. Unlike mocked unit tests, this approach executes real transactions through the `gltest` helper library, confirming that contract deployment, method calls, and state transitions function exactly as they would in production.

## Configuring the gltest Environment

Before running tests, configure the connection parameters in [`gltest.config.yaml`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/gltest.config.yaml). This file defines the RPC endpoint and default account used across all test executions.

By default, gltest targets a local Studio node at `http://127.0.0.1:8545`. The configuration also specifies the **default account**—typically the first pre-funded test address—that serves as the transaction sender for all contract interactions.

```yaml

# gltest.config.yaml

rpc_url: http://127.0.0.1:8545
default_account: "0x..."

```

## The gltest Architecture for Integration Testing

### Contract Factory Pattern

The `get_contract_factory("ContractName")` function returns a factory object capable of deploying fresh contract instances. According to the source code in `genlayerlabs/genlayer-project-boilerplate`, each test should deploy its own contract to ensure complete isolation.

```python
from gltest import get_contract_factory

factory = get_contract_factory("FootballBets")
contract = factory.deploy()

```

### Fixture Reuse with load_fixture

Common setup logic resides in [`tests/integration/fixtures.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/fixtures.py). The `load_fixture` helper imports these reusable components, allowing multiple tests to share deployment code without duplication.

```python
from gltest.helpers import load_fixture
from tests.integration.fixtures import football_bets_win_unresolved

contract = load_fixture(deploy_contract)

```

### Pre-funded Test Accounts

`gltest.default_account` provides a pre-funded address that acts as the signer for all transactions. This account is automatically configured with sufficient balance to cover gas costs during test execution.

```python
from gltest import default_account

sender_address = default_account.address

```

## Writing End-to-End Integration Tests

### Deploying Contract Instances

Each test method should deploy a fresh contract instance to prevent state pollution between test cases. The deployment returns a contract object with methods corresponding to the smart contract functions defined in files like [`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py).

```python
@pytest.mark.integration
def deploy_contract():
    factory = get_contract_factory("FootballBets")
    contract = factory.deploy()
    assert contract.get_points(args=[]) == {}
    return contract

```

### Executing Write Transactions

Invoke contract methods using the deployed contract object. Pass arguments as a list to the `args` parameter. Write operations return transaction objects that can be inspected for success status.

```python
tx = contract.create_bet(args=["2024-06-20", "Spain", "Italy", "1"])

```

### Asserting Transaction Success

The `tx_execution_succeeded` assertion helper from `gltest.assertions` verifies that a transaction did not revert and that gas was consumed as expected.

```python
from gltest.assertions import tx_execution_succeeded

assert tx_execution_succeeded(tx)

```

### Handling Nondeterministic Operations

For methods that call external web APIs (such as `resolve_bet`), use the `wait_interval` and `wait_retries` parameters to poll for completion. This handles the asynchronous nature of real-world data fetches within the contract.

```python
resolve_tx = contract.resolve_bet(
    args=["2024-06-20_spain_italy"],
    wait_interval=10_000,  # milliseconds between retries

    wait_retries=15
)
assert tx_execution_succeeded(resolve_tx)

```

## Complete Integration Test Example

The file [`tests/integration/test_football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/test_football_bets.py) demonstrates the full workflow: deploying a contract, creating a bet, resolving it via external API, and verifying state changes.

```python
import pytest
from gltest import get_contract_factory, default_account
from gltest.helpers import load_fixture
from gltest.assertions import tx_execution_succeeded
from tests.integration.fixtures import football_bets_win_unresolved, football_bets_win_resolved

@pytest.mark.integration
def deploy_contract():
    factory = get_contract_factory("FootballBets")
    contract = factory.deploy()
    assert contract.get_points(args=[]) == {}
    assert contract.get_bets(args=[]) == {}
    return contract

@pytest.mark.integration
def test_football_bets_success_win():
    contract = load_fixture(deploy_contract)

    # Create a bet

    tx = contract.create_bet(args=["2024-06-20", "Spain", "Italy", "1"])
    assert tx_execution_succeeded(tx)

    # Verify initial state

    assert contract.get_bets(args=[]) == {
        default_account.address: football_bets_win_unresolved
    }

    # Resolve the bet (calls external API)

    resolve_tx = contract.resolve_bet(
        args=["2024-06-20_spain_italy"],
        wait_interval=10_000,
        wait_retries=15
    )
    assert tx_execution_succeeded(resolve_tx)

    # Verify resolved state

    assert contract.get_bets(args=[]) == {
        default_account.address: football_bets_win_resolved
    }
    assert contract.get_points(args=[]) == {default_account.address: 1}
    assert contract.get_player_points(args=[default_account.address]) == 1

```

## Key Files in the Testing Workflow

- **[`gltest.config.yaml`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/gltest.config.yaml)** – Configures the RPC endpoint (`http://127.0.0.1:8545`) and default account credentials for the test suite.
- **[`tests/integration/fixtures.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/fixtures.py)** – Contains reusable state definitions and common setup logic imported via `load_fixture`.
- **[`tests/integration/test_football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/test_football_bets.py)** – Full implementation showing deployment patterns and assertion strategies for the `FootballBets` contract.
- **[`contracts/football_bets.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/contracts/football_bets.py)** – The smart contract under test exposing methods like `create_bet`, `resolve_bet`, `get_points`, and `get_player_points`.

## Summary

- **gltest** provides a Python framework for integration testing GenLayer smart contracts against a live Studio node.
- Configure connection settings in [`gltest.config.yaml`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/gltest.config.yaml) and use `default_account` as the transaction signer.
- Deploy fresh contract instances using `get_contract_factory("ContractName").deploy()` to ensure test isolation.
- Reuse setup logic by placing common fixtures in [`tests/integration/fixtures.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/fixtures.py) and loading them with `load_fixture`.
- Assert transaction success using `tx_execution_succeeded` from `gltest.assertions`.
- Handle asynchronous external API calls within contracts using `wait_interval` and `wait_retries` parameters.

## Frequently Asked Questions

### What is gltest in GenLayer?

**gltest** is the official Python testing framework for GenLayer that enables integration testing by connecting to a running GenLayer Studio instance. It provides utilities for deploying contracts, executing transactions, and asserting results against actual on-chain state, differing from unit testing by validating real network interactions rather than mocked behavior.

### How do I configure the Studio connection for integration tests?

Create or modify [`gltest.config.yaml`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/gltest.config.yaml) in your project root to specify the `rpc_url` (default `http://127.0.0.1:8545`) and the `default_account` address. This configuration file is automatically read by gltest helpers to establish the connection and authenticate transactions during test execution.

### Can I reuse contract deployment logic across multiple tests?

Yes. Place common deployment functions in [`tests/integration/fixtures.py`](https://github.com/genlayerlabs/genlayer-project-boilerplate/blob/main/tests/integration/fixtures.py), then import and invoke them using `load_fixture` from `gltest.helpers`. This pattern ensures consistent initial state while maintaining the flexibility to customize specific test scenarios without code duplication.

### How do I handle external API calls in integration tests?

When testing methods like `resolve_bet` that fetch external data, pass `wait_interval` (milliseconds between polls) and `wait_retries` (maximum attempts) parameters to the contract method call. This polling mechanism accommodates the nondeterministic latency of real-world API requests while allowing tests to verify eventual consistency of contract state.