Supertester.GenServerHelpers (supertester v0.1.0)
View SourceSpecialized helpers for GenServer testing patterns.
This module provides utilities specifically designed for testing GenServer behavior, including state management, concurrent testing, and error scenarios.
Key Features
- Safe GenServer state access
- Cast and sync patterns for proper async operation testing
- Concurrent testing utilities
- Error testing and crash recovery
- Timeout-aware GenServer operations
Usage
import Supertester.GenServerHelpers
test "genserver state management" do
{:ok, server} = setup_isolated_genserver(MyGenServer)
state = get_server_state_safely(server)
assert state.counter == 0
end
Summary
Functions
Makes a GenServer call with timeout handling.
Sends a cast and then synchronizes with a sync message.
Performs concurrent calls to a GenServer for stress testing.
Safely retrieves the internal state of a GenServer.
Performs stress testing on a GenServer with various operations.
Tests how a GenServer handles invalid messages.
Tests GenServer crash recovery behavior.
Functions
@spec call_with_timeout(GenServer.server(), term(), timeout()) :: {:ok, term()} | {:error, term()}
Makes a GenServer call with timeout handling.
Parameters
server
- The GenServer pid or namemessage
- The message to sendtimeout
- Timeout in milliseconds (default: 1000)
Returns
{:ok, response}
if successful, {:error, reason}
otherwise
Example
{:ok, response} = call_with_timeout(server, :get_counter, 5000)
@spec cast_and_sync(GenServer.server(), term(), term()) :: :ok | {:ok, term()} | {:error, term()}
Sends a cast and then synchronizes with a sync message.
This is crucial for testing async operations - it ensures the cast has been processed before the test continues.
Parameters
server
- The GenServer pid or namecast_message
- The async message to castsync_message
- The sync message for synchronization (default: :supertester_sync)
Returns
:ok
if successful, {:error, reason}
otherwise
Example
:ok = cast_and_sync(server, {:increment, 5})
{:ok, state} = get_server_state_safely(server)
assert state.counter == 5
@spec concurrent_calls(GenServer.server(), [term()], pos_integer()) :: {:ok, [{term(), [term()]}]}
Performs concurrent calls to a GenServer for stress testing.
Parameters
server
- The GenServer pid or namecalls
- List of messages to send concurrentlycount
- Number of concurrent processes per message (default: 10)
Returns
{:ok, results}
with list of {call, result} tuples
Example
calls = [:get_counter, {:increment, 1}, :get_counter]
{:ok, results} = concurrent_calls(server, calls, 5)
@spec get_server_state_safely(GenServer.server()) :: {:ok, term()} | {:error, term()}
Safely retrieves the internal state of a GenServer.
This function attempts to get the GenServer state without causing crashes if the server is not responsive or doesn't support state inspection.
Parameters
server
- The GenServer pid or name
Returns
{:ok, state}
if successful, {:error, reason}
otherwise
Example
{:ok, state} = get_server_state_safely(my_server)
@spec stress_test_server(GenServer.server(), [term()], pos_integer()) :: {:ok, map()}
Performs stress testing on a GenServer with various operations.
Parameters
server
- The GenServer pid or nameoperations
- List of operations to perform randomlyduration
- Duration in milliseconds (default: 5000)
Returns
{:ok, stats}
with stress test statistics
Example
operations = [
{:call, :get_counter},
{:cast, {:increment, 1}},
{:call, {:add, 5}}
]
{:ok, stats} = stress_test_server(server, operations, 10_000)
@spec test_invalid_messages(GenServer.server(), [term()]) :: {:ok, [{term(), term()}]}
Tests how a GenServer handles invalid messages.
Parameters
server
- The GenServer pid or nameinvalid_messages
- List of invalid messages to test
Returns
{:ok, results}
with test results for each message
Example
invalid_messages = [:invalid_call, {:unknown, :message}, "string_message"]
{:ok, results} = test_invalid_messages(server, invalid_messages)
@spec test_server_crash_recovery(GenServer.server(), term()) :: {:ok, map()} | {:error, term()}
Tests GenServer crash recovery behavior.
Parameters
server
- The GenServer pid or namecrash_reason
- The reason to crash the server with
Returns
{:ok, recovery_info}
if recovery successful, {:error, reason}
otherwise
Example
{:ok, info} = test_server_crash_recovery(server, :test_crash)
assert info.recovered == true