Best Practices & Tips
Learn industry best practices and expert tips to create reliable, maintainable, and scalable automation with Donobu.
Development Best Practices 🎯
Follow these proven practices to build robust and maintainable automation flows.
Flow Design Principles
Start Simple, Build Incrementally
// Good: Start with a basic flow
{
"name": "Simple Login Test",
"targetWebsite": "https://app.example.com/login",
"overallObjective": "Login with valid credentials"
}
// Then enhance with validations
{
"name": "Enhanced Login Test",
"targetWebsite": "https://app.example.com/login",
"overallObjective": "Login with valid credentials and verify dashboard loads",
"resultJsonSchema": {
"type": "object",
"properties": {
"loginSuccess": {"type": "boolean"},
"dashboardLoaded": {"type": "boolean"}
}
}
}
Use Descriptive Names
// Bad
{"name": "Test1"}
// Good
{"name": "User Registration - Happy Path Validation"}
Set Appropriate Limits
{
"maxToolCalls": 15, // Prevent runaway automation
"defaultMessageDuration": 2000, // Reasonable timing
"callbackUrl": "https://your-app.com/webhook" // Get notified when complete
}
Environment Management
Secure Credential Storage
# Store sensitive data as environment variables
curl -X POST http://localhost:31000/api/env/PROD_API_KEY \
-H "Content-Type: application/json" \
-d '{"value": "secret-api-key"}'
# Use descriptive names
curl -X POST http://localhost:31000/api/env/STAGING_ADMIN_PASSWORD \
-H "Content-Type: application/json" \
-d '{"value": "staging-password"}'
Environment-Specific Configurations
{
"name": "Multi-Environment Test",
"targetWebsite": "${BASE_URL}", // Set per environment
"envVars": [
"BASE_URL",
"API_ENDPOINT",
"TEST_USER_EMAIL",
"TEST_USER_PASSWORD"
]
}
Error Handling & Resilience 🛡️
Graceful Error Recovery
Handle Common Scenarios
{
"customTools": [{
"name": "handlePopups",
"description": "Dismisses common popup dialogs",
"inputSchema": {"type": "object", "properties": {}},
"javascript": `
// Handle cookie banners
try {
await page.locator('[id*="cookie"], [class*="cookie"]').first().click({timeout: 2000});
} catch (e) {}
// Handle modal dialogs
try {
await page.locator('[class*="modal"] [class*="close"]').first().click({timeout: 2000});
} catch (e) {}
`
}]
}
Implement Retry Logic
{
"customTools": [{
"name": "retryableClick",
"description": "Clicks element with retry logic",
"inputSchema": {
"type": "object",
"properties": {
"selector": {"type": "string"},
"maxRetries": {"type": "number", "default": 3}
}
},
"javascript": `
for (let i = 0; i < maxRetries; i++) {
try {
await page.locator(selector).click({timeout: 5000});
return {success: true, attempts: i + 1};
} catch (error) {
if (i === maxRetries - 1) throw error;
await page.waitForTimeout(1000);
}
}
`
}]
}
Debugging Strategies
Enable Visual Debugging
{
"browser": {
"using": {
"type": "device",
"headless": false // Watch execution in real-time
}
}
}
Add Diagnostic Information
{
"customTools": [{
"name": "capturePageState",
"description": "Captures current page state for debugging",
"javascript": `
return {
url: page.url(),
title: await page.title(),
viewport: await page.viewportSize(),
cookies: await page.context().cookies(),
localStorage: await page.evaluate(() => ({...localStorage})),
timestamp: new Date().toISOString()
};
`
}]
}
Performance Optimization ⚡
Efficient Execution
Use Appropriate Wait Strategies
{
"customTools": [{
"name": "smartWait",
"description": "Intelligent waiting for dynamic content",
"inputSchema": {
"type": "object",
"properties": {
"selector": {"type": "string"},
"condition": {"type": "string", "enum": ["visible", "hidden", "enabled"]}
}
},
"javascript": `
switch(condition) {
case 'visible':
await page.locator(selector).waitFor({state: 'visible', timeout: 10000});
break;
case 'hidden':
await page.locator(selector).waitFor({state: 'hidden', timeout: 10000});
break;
case 'enabled':
await page.locator(selector).waitFor({state: 'attached'});
await expect(page.locator(selector)).toBeEnabled({timeout: 10000});
break;
}
`
}]
}
Optimize Resource Usage
{
"browser": {
"using": {
"type": "device",
"headless": true // Faster execution in CI/CD
}
},
"maxToolCalls": 20, // Set reasonable limits
"allowedTools": [ // Only include needed tools
"click", "type", "assert", "goToWebpage"
]
}
Parallel Execution
Design for Parallelization
# Create multiple independent flows
curl -X POST http://localhost:31000/api/flows -d '{"name": "Test Suite 1", ...}'
curl -X POST http://localhost:31000/api/flows -d '{"name": "Test Suite 2", ...}'
curl -X POST http://localhost:31000/api/flows -d '{"name": "Test Suite 3", ...}'
# Monitor all flows
curl -X GET "http://localhost:31000/api/flows?state=RUNNING"
Testing Strategies 🧪
Test Pyramid Approach
Level 1: Smoke Tests
- Critical user paths
- Basic functionality validation
- Fast execution (< 2 minutes)
{
"name": "Smoke Test - Core Features",
"overallObjective": "Verify login, dashboard load, and logout work correctly",
"maxToolCalls": 10
}
Level 2: Integration Tests
- Cross-system workflows
- Data validation
- Medium execution time (2-10 minutes)
{
"name": "Integration Test - User Workflow",
"overallObjective": "Complete user registration, profile setup, and first task creation",
"maxToolCalls": 25,
"resultJsonSchema": {
"type": "object",
"properties": {
"userCreated": {"type": "boolean"},
"profileComplete": {"type": "boolean"},
"taskCreated": {"type": "boolean"}
}
}
}
Level 3: End-to-End Tests
- Complete business scenarios
- Full system validation
- Longer execution (10+ minutes)
Data-Driven Testing
Use External Data Sources
{
"customTools": [{
"name": "loadTestData",
"description": "Loads test data from external source",
"javascript": `
const fs = require('fs');
const testData = JSON.parse(fs.readFileSync('./test-data.json', 'utf8'));
return testData.userRegistration[Math.floor(Math.random() * testData.userRegistration.length)];
`
}]
}
Maintenance & Monitoring 📊
Flow Health Monitoring
Set Up Health Checks
# Regular health validation
curl -X POST http://localhost:31000/api/flows \
-H "Content-Type: application/json" \
-d '{
"name": "Health Check - Daily",
"targetWebsite": "https://your-app.com",
"overallObjective": "Verify core application functionality is working",
"callbackUrl": "https://monitoring.yourcompany.com/webhook"
}'
Track Performance Metrics
{
"customTools": [{
"name": "performanceMetrics",
"description": "Tracks key performance indicators",
"javascript": `
const metrics = await page.evaluate(() => {
const navigation = performance.getEntriesByType('navigation')[0];
return {
pageLoadTime: navigation.loadEventEnd - navigation.startTime,
domContentLoaded: navigation.domContentLoadedEventEnd - navigation.startTime,
firstContentfulPaint: performance.getEntriesByName('first-contentful-paint')[0]?.startTime || 0
};
});
// Alert if performance degrades
if (metrics.pageLoadTime > 5000) {
throw new Error(`Page load time ${metrics.pageLoadTime}ms exceeds threshold`);
}
return metrics;
`
}]
}
Version Control & Collaboration
Flow Versioning
{
"name": "User Login v2.1.0",
"description": "Updated to handle new 2FA flow - see CHANGELOG.md",
"metadata": {
"version": "2.1.0",
"author": "team@company.com",
"lastModified": "2024-09-01",
"changelog": "Added support for TOTP authentication"
}
}
Documentation Standards
{
"name": "[SMOKE] User Registration Happy Path",
"description": "Validates new user can register with valid email and password. Covers: email validation, password strength, terms acceptance, email confirmation.",
"overallObjective": "Complete user registration workflow from landing page to email confirmation",
"tags": ["smoke-test", "user-registration", "critical-path"]
}
Security Considerations 🔐
Credential Management
Never Hardcode Secrets
// Bad
{
"overallObjective": "Login with user@example.com and password123"
}
// Good
{
"envVars": ["TEST_USER_EMAIL", "TEST_USER_PASSWORD"],
"overallObjective": "Login with test credentials from environment variables"
}
Use Least Privilege
# Create read-only API keys for testing
# Use test accounts with minimal permissions
# Regularly rotate credentials
Data Protection
Sanitize Sensitive Data
{
"customTools": [{
"name": "sanitizeOutput",
"description": "Removes sensitive data from logs",
"javascript": `
const result = originalResult;
// Remove PII and sensitive data
if (result.email) result.email = result.email.replace(/(.{2}).*(@.*)/, '$1***$2');
if (result.phone) result.phone = result.phone.replace(/\d(?=\d{4})/g, '*');
return result;
`
}]
}
Team Collaboration 🤝
Flow Sharing Standards
Naming Conventions
[TYPE] Feature - Scenario(e.g.,[SMOKE] Login - Valid Credentials)[INTEGRATION] System A to System B - Data Sync[E2E] Purchase Flow - Complete Checkout
Documentation Requirements
- Clear objective description
- Prerequisites and setup requirements
- Expected outcomes and validations
- Failure scenarios and debugging tips
Code Review Process
Review Checklist
- [ ] Descriptive names and documentation
- [ ] Appropriate error handling
- [ ] No hardcoded secrets
- [ ] Reasonable execution limits
- [ ] Performance considerations
- [ ] Test data cleanup
Continuous Improvement 📈
Metrics to Track
Execution Metrics
- Success/failure rates
- Average execution time
- Resource utilization
- Error patterns
Quality Metrics
- Test coverage
- Bug detection rate
- False positive rate
- Maintenance overhead
Regular Maintenance
Weekly Tasks
- Review failing flows
- Update deprecated selectors
- Clean up test data
- Performance optimization
Monthly Tasks
- Flow health assessment
- Documentation updates
- Security review
- Tool and dependency updates
By following these best practices, you'll create automation flows that are reliable, maintainable, and provide long-term value to your team and organization.