buster/api/libs/braintrust/tests/integration_tests.rs

239 lines
6.8 KiB
Rust

use anyhow::Result;
use braintrust::{BraintrustClient, TraceBuilder};
use dotenv::dotenv;
use serde_json::json;
use std::env;
use std::time::Duration;
use tokio::time::sleep;
// Helper function to initialize environment from .env file
fn init_env() -> Result<()> {
// Load environment variables from .env file
dotenv().ok();
// Verify that the API key is set
if env::var("BRAINTRUST_API_KEY").is_err() {
println!("Warning: BRAINTRUST_API_KEY not found in environment or .env file");
println!("Some tests may fail if they require a valid API key");
}
Ok(())
}
#[tokio::test]
async fn test_real_client_initialization() -> Result<()> {
// Initialize environment
init_env()?;
// Create client with environment API key (None means use env var)
let client = BraintrustClient::new(None, "c7b996a6-1c7c-482d-b23f-3d39de16f433")?;
// Simple verification that client was created
assert!(client.project_id() == "c7b996a6-1c7c-482d-b23f-3d39de16f433");
Ok(())
}
#[tokio::test]
async fn test_real_span_logging() -> Result<()> {
// Initialize environment
init_env()?;
// Skip test if no API key is available
if env::var("BRAINTRUST_API_KEY").is_err() {
println!("Skipping test_real_span_logging: No API key available");
return Ok(());
}
// Create client (None means use env var)
let client = BraintrustClient::new(None, "c7b996a6-1c7c-482d-b23f-3d39de16f433")?;
// Create a span
let span = client.create_span("Integration Test Span", "test", None, None);
// Add data to the span
let span = span
.with_input(json!({
"test_input": "This is a test input for integration testing",
"timestamp": chrono::Utc::now().to_rfc3339()
}))
.with_output(json!({
"test_output": "This is a test output for integration testing",
"timestamp": chrono::Utc::now().to_rfc3339()
}))
.with_metadata("test_source", "integration_test")
.with_metadata("test_id", uuid::Uuid::new_v4().to_string());
// Log the span
client.log_span(span).await?;
// Allow some time for async processing
sleep(Duration::from_millis(100)).await;
Ok(())
}
#[tokio::test]
async fn test_real_trace_with_spans() -> Result<()> {
// Initialize environment
init_env()?;
// Skip test if no API key is available
if env::var("BRAINTRUST_API_KEY").is_err() {
println!("Skipping test_real_trace_with_spans: No API key available");
return Ok(());
}
// Create client (None means use env var)
let client = BraintrustClient::new(None, "172afc4a-16b7-4d59-978e-4c87cade87b6")?;
// Create a trace
let trace_id = uuid::Uuid::new_v4().to_string();
let trace = TraceBuilder::new(
client.clone(),
&format!("Integration Test Trace {}", trace_id)
);
// Add a root span
let root_span = trace.add_span("Root Operation", "function").await?;
let mut root_span = root_span
.with_input(json!({
"operation": "root",
"parameters": {
"test": true,
"timestamp": chrono::Utc::now().to_rfc3339()
}
}))
.with_metadata("test_id", trace_id.clone());
// Log the root span
client.log_span(root_span.clone()).await?;
sleep(Duration::from_secs(10)).await;
root_span = root_span
.with_output(json!({
"result": "success",
"parameters": {
"test": true,
"timestamp": chrono::Utc::now().to_rfc3339()
}
}));
client.log_span(root_span).await?;
// Add an LLM span
let llm_span = trace.add_span("LLM Call", "llm").await?;
let mut llm_span = llm_span
.with_input(json!({
"messages": [
{
"role": "user",
"content": "Hello, this is a test message for integration testing"
}
]
}))
.with_metadata("model", "test-model");
// Log the LLM span
client.log_span(llm_span.clone()).await?;
sleep(Duration::from_secs(15)).await;
llm_span = llm_span
.with_output(json!({
"choices": [
{
"message": {
"role": "assistant",
"content": "Hello! I'm responding to your integration test message."
}
}
]
}));
client.log_span(llm_span).await?;
// Add a tool span
let tool_span = trace.add_span("Tool Execution", "tool").await?;
let tool_span = tool_span
.with_input(json!({
"function": {
"name": "test_tool",
"arguments": {
"param1": "value1",
"param2": 42
}
},
"id": uuid::Uuid::new_v4().to_string()
}))
.with_output(json!({
"result": "Tool execution successful",
"data": {
"value": "test result",
"timestamp": chrono::Utc::now().to_rfc3339()
}
}));
// Log the tool span
client.log_span(tool_span).await?;
// Finish the trace
trace.finish().await?;
// Allow some time for async processing
sleep(Duration::from_secs(30)).await;
Ok(())
}
#[tokio::test]
async fn test_real_error_handling() -> Result<()> {
// Initialize environment
init_env()?;
// Skip test if no API key is available
if env::var("BRAINTRUST_API_KEY").is_err() {
println!("Skipping test_real_error_handling: No API key available");
return Ok(());
}
// Create client (None means use env var)
let client = BraintrustClient::new(None, "c7b996a6-1c7c-482d-b23f-3d39de16f433")?;
// Create a trace for error testing
let trace = TraceBuilder::new(
client.clone(),
"Integration Test Error Handling"
);
// Add a span that will contain an error
let error_span = trace.add_span("Error Operation", "function").await?;
// Simulate an operation that results in an error
let error_message = "This is a simulated error for testing";
let error_span = error_span
.with_input(json!({
"operation": "error_test",
"should_fail": true
}))
.with_output(json!({
"error": error_message,
"stack_trace": "simulated stack trace for testing",
"timestamp": chrono::Utc::now().to_rfc3339()
}))
.with_metadata("error", true)
.with_metadata("error_type", "SimulatedError");
// Log the error span
client.log_span(error_span).await?;
// Finish the trace
trace.finish().await?;
// Allow some time for async processing
sleep(Duration::from_millis(100)).await;
Ok(())
}