Integration Testing

The test kit also facilitates integration testing, allowing you to simulate the interaction between multiple players, servers, and the blockchain. You can:

  • Create multiple test clients: Instantiate TestClient objects for each player and server you want to simulate.

// Rust example
use race_test::TestClient;
use race_core::types::ClientMode;

// Create test clients for players
let mut alice = TestClient::player("Alice");
let mut bob = TestClient::player("Bob");

// Create test clients for servers (transactor and validators)
let mut transactor = TestClient::transactor("Foo");
let mut validator1 = TestClient::validator("Bar");
let mut validator2 = TestClient::validator("Baz");
  • Set up the game environment: Create a test game account and initialize the game context and handler as in unit testing.

// Rust example
use race_test::TestGameAccountBuilder;
use race_core::context::GameContext;
use race_test::TestHandler;

// Define your game's account data structure
#[derive(BorshSerialize, BorshDeserialize)]
struct MyGameData {
    // ... game-specific data fields
}

// Create a test game account
let game_account = TestGameAccountBuilder::default()
    .add_player(&mut alice, 1000)
    .add_player(&mut bob, 1000)
    .set_transactor(&mut transactor)
    .add_validator(&mut validator1)
    .add_validator(&mut validator2)
    .with_data(MyGameData { /* ... */ })
    .build();

// Create the game context
let mut ctx = GameContext::try_new(&game_account).unwrap();

// Initialize your game handler (replace MyGameHandler with your actual handler)
let mut handler = TestHandler::<MyGameHandler>::init_state(&mut ctx, &game_account).unwrap();
  • Simulate game flow: Use the test clients to send events, interact with the game, and observe the overall game flow and interactions between components.

// Simulate game start event
let event = ctx.gen_start_game_event();
handler.handle_event(&mut ctx, &event).unwrap();

// Loop to simulate game events and interactions
while let Some(dispatch_event) = ctx.get_dispatch() {
    // Handle dispatched events (e.g., timeouts)
    handler.handle_dispatch_event(&mut ctx).unwrap();

    // Simulate player actions and server responses
    // ... (use test clients to send events and update context)

    // Handle events generated by clients and the updated context
    handler.handle_until_no_events(&mut ctx, vec![&mut alice, &mut bob, &mut transactor, &mut validator1, &mut validator2]).unwrap();
}
  • Verify settlements: After the game concludes, verify that the generated settlements and asset distributions are correct and match the game outcome.

// After the game loop ends, verify settlements
let settles = ctx.get_settles().unwrap();

// Assert that the settlements are correct based on the game outcome
// ... (e.g., check if the winner received the pot, players' balances are updated)

Remember:

  • Adapt these examples to your specific game logic and testing needs.

  • The handle_until_no_events function is useful for simulating the event loop and handling events generated by clients and the updated context.

  • Use assertions to verify the expected game state, effects, and settlements throughout the simulation.

By following these steps and using the Race test kit effectively, you can perform comprehensive integration testing for your Race Protocol game bundles.

Integration Testing Example

WASM Bundle and Client-Side (Combined)

Here's an example of integration testing using the Race test kit to simulate a game flow with multiple players, involving both the WASM bundle and client-side code:

// Rust code for setting up the game environment and simulating server interactions
use race_test::{TestClient, TestGameAccountBuilder, TestHandler};

... (Set up game account, context, and handler) ...

let mut server_client = TestClient::new(context.clone(), handler.clone());
let mut player1_client = TestClient::new(context.clone(), handler.clone());
let mut player2_client = TestClient::new(context, handler);

// Simulate game flow with events from server and players
... (Send events and interact with the game) ...

// Assert the expected final state and settlements
let final_state = server_client.context().handler_state();
let settlements = server_client.context().settlements();

assert_eq!(final_state, expected_final_state);
assert_eq!(settlements, expected_settlements);
// TypeScript code for simulating client interactions
import { TestClient } from '@race-foundation/sdk-core';

... (Connect to the game using AppClient or SubClient) ...

// Simulate player actions and event exchange
await player1Client.submitEvent({ type: 'joinGame', ... });
await player2Client.submitEvent({ type: 'joinGame', ... });

await player1Client.submitEvent({ type: 'playerMove', ... });
await player2Client.submitEvent({ type: 'playerMove', ... });

// Observe game state updates and revealed information
... (Handle events and update UI) ...

This combined example shows how to use the test kit to simulate interactions on both the server and client sides, allowing you to test the overall game flow and verify the final state and settlements.

Last updated