Packages
Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.
Current section
Files
Jump to
Current section
Files
lib/raxol/test/performance/assertions.ex
defmodule Raxol.Test.Performance.Assertions do
@moduledoc """
Provides assertions for performance testing of Raxol components.
This module includes assertions for:
- Render time thresholds
- Memory usage limits
- Event latency requirements
- Resource utilization bounds
"""
import ExUnit.Assertions
alias Raxol.Test.Performance
@doc """
Asserts that a component renders within a specified time limit.
## Example
assert_render_time component, fn ->
render_iterations(component, 1000)
end, under: 100 # milliseconds
"""
def assert_render_time(component, operation, opts \\ []) do
time = Performance.measure_render_time(component, operation)
threshold =
Keyword.get(opts, :under, component.benchmark_config.max_render_time)
assert time <= threshold,
"Render time #{time}ms exceeds threshold of #{threshold}ms"
end
@doc """
Asserts that a component's memory usage stays within specified limits.
## Example
assert_memory_usage component, fn ->
render_with_large_dataset(component)
end, under: 1024 * 1024 # 1MB
"""
def assert_memory_usage(component, operation, opts \\ []) do
usage = Performance.measure_memory_usage(component, operation)
threshold =
Keyword.get(opts, :under, component.benchmark_config.max_memory_usage)
assert usage.total <= threshold,
"Memory usage #{usage.total} bytes exceeds threshold of #{threshold} bytes"
# Return detailed memory stats for analysis
{:ok, usage}
end
@doc """
Asserts that event handling latency stays within acceptable bounds.
## Example
assert_event_latency component, :click, under: 10 # milliseconds
"""
def assert_event_latency(component, event, opts \\ []) do
latency = Performance.measure_event_latency(component, event)
threshold =
Keyword.get(opts, :under, component.benchmark_config.max_event_latency)
assert latency <= threshold,
"Event latency #{latency}ms exceeds threshold of #{threshold}ms"
end
@doc """
Asserts that a component's resource utilization remains stable.
## Example
assert_stable_resource_usage component, duration: 1000
"""
def assert_stable_resource_usage(component, opts \\ []) do
duration = Keyword.get(opts, :duration, 1000)
measurements = Performance.track_resource_utilization(component, duration)
# Analyze memory stability
memory_trend = analyze_trend(measurements, & &1.memory[:total])
assert memory_trend.stable?,
"Memory usage is not stable: #{inspect(memory_trend)}"
# Analyze process count stability
process_trend = analyze_trend(measurements, & &1.process_count)
assert process_trend.stable?,
"Process count is not stable: #{inspect(process_trend)}"
{:ok, %{memory: memory_trend, processes: process_trend}}
end
@doc """
Asserts that a component's performance metrics meet all requirements.
## Example
assert_performance_requirements component, %{
render_time: 100,
memory_usage: 1024 * 1024,
event_latency: 10
}
"""
def assert_performance_requirements(component, requirements) do
results = Performance.run_benchmark_suite(component)
Enum.each(requirements, fn {metric, threshold} ->
value = get_in(results, [metric])
assert value <= threshold,
"#{metric} #{value} exceeds requirement of #{threshold}"
end)
{:ok, results}
end
@doc """
Asserts that a component's performance hasn't regressed from baseline.
## Example
assert_no_performance_regression component, "button_baseline"
"""
def assert_no_performance_regression(component, baseline_name) do
current = Performance.run_benchmark_suite(component)
baseline = load_performance_baseline(baseline_name)
Enum.each([:render_time, :memory_usage, :event_latency], fn metric ->
current_value = get_in(current, [metric])
baseline_value = get_in(baseline, [metric])
# Allow for some variation (e.g., 10% above baseline)
threshold = baseline_value * 1.1
assert current_value <= threshold,
"""
Performance regression detected for #{metric}:
Current: #{current_value}
Baseline: #{baseline_value}
Threshold: #{threshold}
"""
end)
end
# Private Helpers
defp analyze_trend(measurements, value_fn) do
values = Enum.map(measurements, value_fn)
mean = Enum.sum(values) / length(values)
stddev = calculate_stddev(values, mean)
%{
mean: mean,
stddev: stddev,
# Consider stable if stddev is within 10% of mean
stable?: stddev / mean <= 0.1
}
end
defp calculate_stddev(values, mean) do
variance =
Enum.reduce(values, 0, fn value, acc ->
diff = value - mean
acc + diff * diff
end) / length(values)
:math.sqrt(variance)
end
defp load_performance_baseline(_name) do
# baseline_path = get_baseline_path()
# Add baseline loading logic
# For now, return default values
%{
render_time: 50,
memory_usage: 512 * 1024,
event_latency: 5
}
end
# Placeholder function
# defp get_baseline_path() do
# # NOTE: Define logic to get the actual baseline path in the future.
# "test/performance/baselines/default.json"
# end
end