Testing & Development
Complete guide for testing your OilPriceAPI integration without affecting production quotas or incurring charges.
Test Environment
OilPriceAPI provides a dedicated test environment for development and testing purposes.
Test API Keys
Test keys allow you to develop and test your integration without using production quotas:
- Format:
opa_test_*
(e.g.,opa_test_a1b2c3d4e5f6
) - Quotas: 100 requests/day (separate from production)
- Data: Returns realistic but not real-time data
- Charges: No charges for test requests
- Rate Limits: Same as production (60 req/min)
Getting Test Keys
- Log into your dashboard
- Navigate to API Keys → Test Keys
- Click Create Test Key
- Name it descriptively (e.g., "CI/CD Testing")
- Copy immediately - shown only once
Test Data Characteristics
Price Data
Test environment returns realistic price data with:
- Prices from a fixed point in time (updated weekly)
- Realistic price variations and patterns
- All commodity codes available
- Historical data for past periods
Response Format
Identical to production - same JSON structure, fields, and headers.
What's Different
- Prices are not real-time (frozen snapshot)
- Webhook events are simulated
- WebSocket streams replay recorded data
- No impact on production quotas
Testing Strategies
1. Unit Testing
import os
import pytest
import requests
@pytest.fixture
def api_headers():
"""Use test key for unit tests"""
return {
'Authorization': f"Token {os.environ['OILPRICE_TEST_KEY']}"
}
def test_get_prices(api_headers):
response = requests.get(
'https://api.oilpriceapi.com/v1/prices/latest?by_code=WTI_USD',
headers=api_headers
)
data = response.json()
assert data['status'] == 'success'
assert 'WTI_USD' in data['data']
assert 'price' in data['data']['WTI_USD']
2. Integration Testing
// integration.test.js
describe('OilPriceAPI Integration', () => {
const apiKey = process.env.OILPRICE_TEST_KEY;
const baseURL = 'https://api.oilpriceapi.com/v1';
async function fetchPrices(commodity = 'WTI_USD') {
const response = await fetch(
`${baseURL}/prices/latest?by_code=${commodity}`,
{
headers: {
'Authorization': `Token ${apiKey}`
}
}
);
return response.json();
}
test('fetch latest prices', async () => {
const prices = await fetchPrices();
expect(prices.status).toBe('success');
expect(prices.data).toBeDefined();
});
test('handle rate limits', async () => {
// Test rate limit handling
const requests = Array(70).fill().map(() => fetchPrices());
const results = await Promise.allSettled(requests);
const rateLimited = results.filter(r =>
r.reason?.message?.includes('429')
);
expect(rateLimited.length).toBeGreaterThan(0);
});
});
3. Error Handling Testing
def test_error_handling():
"""Test various error scenarios"""
# Test invalid commodity code
response = requests.get(
'https://api.oilpriceapi.com/v1/prices/latest?by_code=INVALID_CODE',
headers={'Authorization': f"Token {os.environ['OILPRICE_TEST_KEY']}"}
)
assert response.status_code == 400
data = response.json()
assert data['status'] == 'error'
assert 'INVALID_COMMODITY' in data.get('error', {}).get('code', '')
# Test missing authentication
response = requests.get(
'https://api.oilpriceapi.com/v1/prices/latest'
)
assert response.status_code == 401
4. Load Testing
# Using Apache Bench for load testing
# Test with 100 requests, 10 concurrent
ab -n 100 -c 10 \
-H "Authorization: Token opa_test_YOUR_KEY" \
https://api.oilpriceapi.com/v1/prices/latest
# Using k6 for more complex scenarios
cat > load-test.js << EOF
import http from 'k6/http';
import { check } from 'k6';
export let options = {
stages: [
{ duration: '30s', target: 10 }, // Ramp up
{ duration: '1m', target: 10 }, // Stay at 10
{ duration: '30s', target: 0 }, // Ramp down
],
};
export default function() {
let response = http.get('https://api.oilpriceapi.com/v1/prices/latest', {
headers: { 'Authorization': 'Token opa_test_YOUR_KEY' },
});
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
}
EOF
k6 run load-test.js
CI/CD Integration
GitHub Actions
name: API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Run tests
env:
OILPRICE_TEST_KEY: ${{ secrets.OILPRICE_TEST_KEY }}
run: npm test
Environment Variables
# .env.test
OILPRICE_API_KEY=opa_test_YOUR_TEST_KEY
OILPRICE_BASE_URL=https://api.oilpriceapi.com/v1
# .env.production
OILPRICE_API_KEY=opa_live_YOUR_LIVE_KEY
OILPRICE_BASE_URL=https://api.oilpriceapi.com/v1
Mock Server for Offline Testing
For testing without network access, use our mock server:
// mock-server.js
const express = require('express');
const app = express();
// Mock responses
const mockData = {
'/v1/prices/latest': {
status: 'success',
data: {
WTI_USD: {
price: 78.45,
currency: 'USD',
unit: 'barrel',
timestamp: new Date().toISOString()
}
}
}
};
app.get('/v1/*', (req, res) => {
const path = req.path;
if (mockData[path]) {
res.json(mockData[path]);
} else {
res.status(404).json({
status: 'error',
error: { code: 'NOT_FOUND' }
});
}
});
app.listen(3001, () => {
console.log('Mock API server running on http://localhost:3001');
});
Testing Webhooks
Test webhook endpoints without exposing local servers:
Using ngrok
# Start your local webhook server
node webhook-server.js
# In another terminal, expose it via ngrok
ngrok http 3000
# Configure webhook URL in dashboard
# https://abc123.ngrok.io/webhook
Webhook Test Server
// webhook-test-server.js
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhook', (req, res) => {
// Verify signature (see webhook verification guide)
const signature = req.headers['x-oilprice-signature'];
const payload = JSON.stringify(req.body);
const expectedSig = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSig) {
return res.status(401).send('Invalid signature');
}
// Process webhook
console.log('Webhook received:', req.body);
// Respond quickly
res.status(200).send('OK');
// Process async
processWebhookAsync(req.body);
});
app.listen(3000);
Testing Best Practices
1. Use Test Keys in Development
- Never commit production keys
- Use environment variables
- Separate test/production configs
2. Test Rate Limit Handling
- Implement exponential backoff
- Test retry logic
- Handle 429 responses gracefully
3. Test Error Scenarios
- Network failures
- Invalid inputs
- Authentication errors
- Rate limiting
4. Monitor Test Usage
- Track test request counts
- Alert on approaching limits
- Review test efficiency
5. Test Data Validation
// Validate response structure
function validatePriceResponse(response) {
assert(response.status === 'success');
assert(typeof response.data === 'object');
Object.values(response.data).forEach(commodity => {
assert(typeof commodity.price === 'number');
assert(commodity.price > 0);
assert(typeof commodity.currency === 'string');
assert(typeof commodity.timestamp === 'string');
});
}
Transitioning to Production
When ready to go live:
Replace API Keys
# Development OILPRICE_API_KEY=opa_test_abc123 # Production OILPRICE_API_KEY=opa_live_xyz789
Update Configuration
- Remove test flags
- Update webhook URLs
- Configure production error handling
Verify Production Access
- Test with small request volume
- Monitor error rates
- Check quota usage
Monitor Performance
- Response times
- Error rates
- Rate limit usage
Troubleshooting Test Environment
Issue: Test key not working
- Verify key format starts with
opa_test_
- Check dashboard for key status
- Ensure not exceeding 100 req/day limit
Issue: Different data than expected
- Test data is frozen snapshot
- Updated weekly, not real-time
- Use production for live data
Issue: Webhooks not triggering
- Test webhooks are simulated
- May have slight delays
- Check webhook URL configuration
Support
For test environment issues:
- Email: [email protected]
- Include test key (first 8 chars)
- Describe expected vs actual behavior
- Response within 3 business days