This document outlines comprehensive testing workflows to ensure full Restreamer create/monitor/control functionality.
- OBS Studio: Latest stable version (30.x+)
- Restreamer Server: datarhei/core v3.x running locally or remote
- Test Accounts: Valid stream keys for at least 2 platforms (Twitch, YouTube, etc.)
- Network: Stable internet connection for streaming tests
# Option 1: Docker local server
docker run -d \
--name restreamer \
-p 8080:8080 \
-p 1935:1935 \
-p 6000:6000/udp \
datarhei/restreamer:latest
# Option 2: Use existing Restreamer server
# Configure connection details: host, port, username, passwordObjective: Verify plugin can connect to Restreamer server
Steps:
- Open OBS Studio
- Navigate to View → Docks → Restreamer Dock
- In "Connection" tab, enter:
- Host:
localhost(or server IP) - Port:
8080 - HTTPS: Unchecked (for local) or Checked (for production)
- Username:
admin - Password: (your password)
- Host:
- Click "Test" button
Expected Results:
- ✅ Connection status changes to "● Connected" (green)
- ✅ Status message displays server info
- ✅ No errors in OBS log
Log Verification:
grep -i "polyemesis.*login\|connected" ~/Library/Application\ Support/obs-studio/logs/*.txtObjective: Verify proper error handling for auth failures
Steps:
- Enter incorrect password
- Click "Test" button
Expected Results:
- ❌ Connection status shows "● Authentication failed" (red)
- ❌ Error message displayed to user
- ✅ Plugin remains functional (no crash)
Objective: Verify connection settings persist across OBS restarts
Steps:
- Connect successfully
- Quit OBS
- Restart OBS
- Check connection status
Expected Results:
- ✅ Connection credentials remembered
- ✅ Auto-reconnect on startup (if enabled)
Objective: Test plugin behavior during network issues
Steps:
- Connect successfully
- Disconnect network OR stop Restreamer server
- Wait 30 seconds
- Restore network OR restart Restreamer
Expected Results:
⚠️ Connection status shows "● Disconnected"- ✅ Plugin doesn't crash
- ✅ Auto-reconnect works when network restored
- ✅ Error messages are user-friendly
Objective: Verify profile creation workflow
Steps:
- Click "Create Profile" button
- Enter profile name: "Test_Profile_1"
- Click OK
Expected Results:
- ✅ Profile appears in profile list
- ✅ Profile saved to settings
- ✅ Profile status shows "INACTIVE"
- ✅ Buttons enabled: Edit, Duplicate, Start
Objective: Test profile configuration dialog
Steps:
- Select "Test_Profile_1"
- Click "Configure" button
- Modify settings:
- Profile Name: "Horizontal_Stream"
- Source Orientation: Horizontal (16:9)
- Auto-detect: Checked
- Auto-start: Unchecked
- Auto-reconnect: Checked
- Input URL:
rtmp://localhost/live/obs_input
- Click "Save"
Expected Results:
- ✅ Settings saved successfully
- ✅ Profile name updated in list
- ✅ Changes persist after OBS restart
Objective: Test multi-destination streaming
Steps:
- Configure profile "Horizontal_Stream"
- Click "Add Destination":
- Destination 1:
- Service: Twitch
- Stream Key: (valid Twitch key)
- Target Orientation: Horizontal
- Enabled: ✓
- Destination 2:
- Service: YouTube
- Stream Key: (valid YouTube key)
- Target Orientation: Horizontal
- Enabled: ✓
- Destination 1:
- Save profile
Expected Results:
- ✅ Both destinations appear in destinations table
- ✅ Profile summary shows "2 destinations"
- ✅ Stream keys masked in UI (only show first 4 and last 4 chars)
Objective: Test destination modification
Steps:
- Select destination in table
- Click "Edit Destination"
- Change target orientation to Vertical
- Save changes
Expected Results:
- ✅ Destination updated successfully
- ✅ Changes reflected in table
- ✅ Profile marked as modified
Objective: Test destination deletion
Steps:
- Select destination
- Click "Remove Destination"
- Confirm deletion
Expected Results:
- ✅ Destination removed from table
- ✅ Profile destination count decremented
- ✅ No crashes or errors
Objective: Test profile cloning
Steps:
- Select "Horizontal_Stream"
- Click "Duplicate"
- Enter name: "Horizontal_Stream_Copy"
Expected Results:
- ✅ New profile created with all settings copied
- ✅ Destinations copied correctly
- ✅ New profile has unique ID
Objective: Test profile deletion
Steps:
- Select profile (must be INACTIVE)
- Click "Delete"
- Confirm deletion
Expected Results:
- ✅ Profile removed from list
- ✅ Settings file updated
- ✅ Cannot delete ACTIVE profile (button disabled)
Objective: Test right-click menu
Steps:
- Right-click on profile in list
- Test each menu option
Expected Results:
- ✅ Context menu appears
- ✅ Menu items enabled/disabled based on profile status
- ✅ All actions work correctly
Objective: Verify profile can start streaming
Pre-conditions:
- OBS is streaming (to generate source content)
- Profile has at least 1 destination configured
Steps:
- Start OBS streaming first
- Select profile
- Click "▶ Start" button
- Monitor status for 30 seconds
Expected Results:
- ✅ Profile status changes: INACTIVE → STARTING → ACTIVE
- ✅ Start button disabled, Stop button enabled
- ✅ Process created on Restreamer server
- ✅ No errors in logs
Verification Commands:
# Check Restreamer processes
curl -u admin:password http://localhost:8080/api/v3/process | jq
# Check OBS logs
tail -f ~/Library/Application\ Support/obs-studio/logs/*.txt | grep polyemesisObjective: Verify real-time monitoring works
Steps:
- With stream active, observe metrics:
- Process state (ACTIVE/STARTING/ERROR)
- Uptime counter
- CPU usage
- Memory usage
- Frames processed
- Dropped frames
- FPS
- Bitrate
- Progress indicator
Expected Results:
- ✅ All metrics update every 2-5 seconds
- ✅ Values are realistic (FPS ~30, bitrate matches settings)
- ✅ No negative values or errors
Objective: Verify clean shutdown
Steps:
- With profile ACTIVE
- Click "■ Stop" button
- Wait for state transition
Expected Results:
- ✅ Profile status: ACTIVE → STOPPING → INACTIVE
- ✅ Process removed from Restreamer
- ✅ Metrics cleared/reset
- ✅ No hanging processes
Objective: Test bulk start operation
Steps:
- Create 3 profiles with different destinations
- Click "▶ All" button
- Monitor all profiles
Expected Results:
- ✅ All profiles start simultaneously
- ✅ Each profile transitions independently
- ✅ No race conditions or conflicts
- ✅ System remains responsive
Objective: Test bulk stop operation
Steps:
- With all profiles ACTIVE
- Click "■ All" button
- Wait for completion
Expected Results:
- ✅ All profiles stop cleanly
- ✅ All processes removed
- ✅ No orphaned streams
Objective: Test profile behavior when OBS stops streaming
Steps:
- Start OBS streaming
- Start profile
- Stop OBS streaming
- Wait 10 seconds
- Start OBS streaming again
Expected Results:
⚠️ Profile shows error or stops (no input source)- ✅ Auto-reconnect triggers when OBS resumes
- ✅ Or profile remains stopped (depending on auto-reconnect setting)
Objective: Verify streams actually reach destinations
Steps:
- Start profile with Twitch destination
- Open Twitch dashboard
- Check "Stream Manager" for live indicator
- Verify video appears
Expected Results:
- ✅ Stream goes live on Twitch
- ✅ Video quality matches settings
- ✅ Audio present (if configured)
- ✅ No buffering or stuttering
Objective: Test handling of authentication failures at destination
Steps:
- Configure destination with invalid stream key
- Start profile
- Monitor status
Expected Results:
- ❌ Profile shows ERROR status
- ❌ Error message indicates auth failure
- ✅ Plugin remains stable (no crash)
- ✅ Other destinations continue if valid
Objective: Test resilience to network issues
Steps:
- Start profile
- Disable network for 10 seconds
- Re-enable network
Expected Results:
⚠️ Profile shows error/disconnected- ✅ Auto-reconnect attempts (if enabled)
- ✅ Stream resumes when network restored
- ✅ Or clean error state if auto-reconnect off
Objective: Test plugin behavior when server goes down
Steps:
- Start profile
- Stop Restreamer server:
docker stop restreamer - Wait 30 seconds
- Restart server:
docker start restreamer
Expected Results:
- ❌ Connection status shows disconnected
- ✅ Plugin doesn't crash
- ✅ Auto-reconnect when server returns
- ✅ Profiles show correct state after reconnect
Objective: Test cleanup on unexpected exit
Steps:
- Start profile
- Force quit OBS (kill -9)
- Restart OBS
- Check Restreamer processes
Expected Results:
- ✅ Profile state restored correctly
- ✅ No orphaned processes on Restreamer
⚠️ Or orphaned process cleaned up after timeout
Objective: Test handling of bad configuration
Steps:
- Configure profile with invalid Input URL:
rtmp://invalid:1935/live/test - Start profile
Expected Results:
- ❌ Profile shows ERROR status
- ❌ Error message: "Input source unreachable" or similar
- ✅ Plugin remains stable
Objective: Test behavior under network constraints
Steps:
- Configure high bitrate (6000+ kbps)
- Start stream on limited connection
- Monitor dropped frames
Expected Results:
⚠️ High dropped frame count displayed⚠️ Warning indicator (if implemented)- ✅ Stream continues (degraded quality)
- ✅ Metrics accurately reflect issues
Objective: Test system limits
Steps:
- Create 5 profiles with 2 destinations each (10 streams total)
- Start all profiles simultaneously
- Monitor for 5 minutes
Expected Results:
- ✅ All streams start successfully
- ✅ CPU usage reasonable (<50%)
- ✅ No memory leaks
- ✅ UI remains responsive
- ✅ All streams stable
Monitoring:
# Monitor OBS CPU/memory
top -pid $(pgrep OBS)
# Monitor Restreamer processes
watch -n 1 'curl -s -u admin:password http://localhost:8080/api/v3/process | jq ".[].state"'Objective: Test stability over extended period
Steps:
- Start profile
- Leave running for 24 hours
- Monitor metrics periodically
Expected Results:
- ✅ No crashes or hangs
- ✅ Memory usage stable (no leaks)
- ✅ Stream quality consistent
- ✅ Metrics continue updating
Objective: Test state management under stress
Steps:
- Create script to start/stop profile every 10 seconds
- Run for 50 cycles (10 minutes)
Expected Results:
- ✅ All state transitions complete
- ✅ No race conditions
- ✅ No orphaned processes
- ✅ Plugin remains stable
Objective: Verify settings follow OBS profile changes
Steps:
- Configure plugin in OBS Profile 1
- Switch to OBS Profile 2
- Configure different settings
- Switch back to Profile 1
Expected Results:
- ✅ Settings restore correctly for each OBS profile
- ✅ Active streams maintain state during switch
Objective: Test behavior during scene transitions
Steps:
- Start profile with RTMP input from OBS
- Change OBS scenes during stream
Expected Results:
- ✅ Stream continues without interruption
- ✅ Scene changes reflected in output
- ✅ No dropped frames during transition
Objective: Test remote control via obs-websocket
Steps:
- Connect obs-websocket client
- Send vendor request:
GetProfiles - Send vendor request:
StartProfile {profileId: "..."} - Send vendor request:
StopProfile {profileId: "..."}
Expected Results:
- ✅ API responds with correct data
- ✅ Profile control works remotely
- ✅ Events emitted for state changes
Objective: Verify UI in both light and dark themes
Steps:
- Test in OBS Dark theme (default)
- Switch to Light theme (Settings → General → Theme)
- Verify all UI elements
Expected Results:
- ✅ All text readable (sufficient contrast)
- ✅ Buttons/inputs styled correctly
- ✅ Status colors visible
- ✅ No visual glitches
Objective: Test responsive layout
Steps:
- Resize OBS window to minimum size
- Resize to maximum
- Resize dock panel specifically
Expected Results:
- ✅ No content cutoff
- ✅ Scrollbars appear when needed
- ✅ Layout remains usable
Objective: Test keyboard navigation
Steps:
- Use Tab key to navigate between fields
- Test in Connection tab
- Test in Output Profiles tab
- Test in Process List tab
Expected Results:
- ✅ Tab order logical (top-to-bottom, left-to-right)
- ✅ All interactive elements reachable
- ✅ Visual focus indicator present
Objective: Verify helpful tooltips present
Steps:
- Hover over each button/field
- Check for tooltips
Expected Results:
- ✅ All buttons have tooltips
- ✅ Tooltips are descriptive
- ✅ Technical fields have explanations
Objective: Verify credentials stored securely
Steps:
- Configure connection with password
- Check settings file:
~/Library/Application Support/obs-studio/plugin_config/obs-polyemesis/config.json
Expected Results:
- ✅ Password not stored in plaintext
- ✅ Or file permissions restrictive (600)
⚠️ Consider keychain integration
Objective: Verify stream keys not exposed
Steps:
- Configure destination with stream key
- Check UI displays
- Check logs
- Check screenshots
Expected Results:
- ✅ Keys masked in UI (e.g., "abc***xyz")
- ✅ Keys not logged in plaintext
- ✅ Keys not visible in profile list
Objective: Test secure connection to Restreamer
Steps:
- Configure HTTPS endpoint
- Enable HTTPS checkbox
- Test connection
Expected Results:
- ✅ TLS handshake succeeds
- ✅ Certificate validation works
- ✅ No certificate warnings (if valid cert)
Platform: macOS 12+ (Intel and Apple Silicon)
Key Tests:
- ✅ Plugin loads correctly
- ✅ All UI elements render
- ✅ Streaming works
- ✅ No crashes on quit
Platform: Windows 10/11
Key Tests:
- ✅ Plugin installation successful
- ✅ DLL dependencies resolved
- ✅ Paths correct (Windows-style)
- ✅ All functionality works
Platform: Ubuntu 22.04+ / Fedora 38+
Key Tests:
- ✅ Plugin loads
- ✅ Library dependencies met
- ✅ X11/Wayland compatibility
- ✅ All tests pass
Connection:
- Connect to Restreamer server
- Test connection button works
- Credentials persist across restarts
Profile Management:
- Create profile
- Configure profile settings
- Add destination
- Edit destination
- Remove destination
- Delete profile
- Duplicate profile
Stream Control:
- Start single profile
- Monitor active stream
- Stop profile
- Start all profiles
- Stop all profiles
Error Handling:
- Invalid credentials
- Invalid stream key
- Network failure
- Server unavailable
UI/UX:
- Dark theme
- Light theme
- Window resize
- Tab navigation
#!/bin/bash
# scripts/test-polyemesis.sh
set -e
echo "=========================================="
echo " OBS Polyemesis Automated Test Suite"
echo "=========================================="
# Check prerequisites
echo "[1/10] Checking prerequisites..."
command -v obs >/dev/null 2>&1 || { echo "Error: OBS not installed"; exit 1; }
command -v docker >/dev/null 2>&1 || { echo "Error: Docker not installed"; exit 1; }
command -v curl >/dev/null 2>&1 || { echo "Error: curl not installed"; exit 1; }
command -v jq >/dev/null 2>&1 || { echo "Error: jq not installed"; exit 1; }
# Start Restreamer server
echo "[2/10] Starting Restreamer server..."
docker run -d --rm --name restreamer-test \
-p 8080:8080 \
-p 1935:1935 \
datarhei/restreamer:latest
sleep 10
# Wait for server ready
echo "[3/10] Waiting for Restreamer API..."
for i in {1..30}; do
if curl -s http://localhost:8080/api/v3/about >/dev/null; then
echo "Server ready!"
break
fi
echo "Waiting... ($i/30)"
sleep 1
done
# Test 1: API health check
echo "[4/10] Testing API health..."
curl -s -u admin:admin http://localhost:8080/api/v3/about | jq .name
# Test 2: Login endpoint
echo "[5/10] Testing login..."
TOKEN=$(curl -s -X POST http://localhost:8080/api/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin"}' \
| jq -r .access_token)
if [ -n "$TOKEN" ] && [ "$TOKEN" != "null" ]; then
echo "✅ Login successful"
else
echo "❌ Login failed"
exit 1
fi
# Test 3: Process list
echo "[6/10] Testing process list..."
PROCESSES=$(curl -s -u admin:admin http://localhost:8080/api/v3/process | jq length)
echo "Found $PROCESSES processes"
# Test 4: Create process
echo "[7/10] Testing process creation..."
PROCESS_JSON=$(cat <<EOF
{
"id": "test_obs_stream",
"reference": "obs-polyemesis-test",
"input": [
{
"address": "rtmp://localhost/live/obs_input",
"id": "input_0"
}
],
"output": [
{
"address": "rtmp://localhost/live/test_output",
"id": "output_0"
}
],
"options": ["-f", "flv"]
}
EOF
)
curl -s -X POST http://localhost:8080/api/v3/process \
-u admin:admin \
-H "Content-Type: application/json" \
-d "$PROCESS_JSON" | jq .id
# Test 5: Check process exists
echo "[8/10] Verifying process created..."
PROCESS_ID=$(curl -s -u admin:admin http://localhost:8080/api/v3/process | jq -r '.[0].id')
echo "Process ID: $PROCESS_ID"
# Test 6: Start process (will fail without real input, that's OK)
echo "[9/10] Testing process control..."
curl -s -X PUT http://localhost:8080/api/v3/process/$PROCESS_ID/command \
-u admin:admin \
-H "Content-Type: application/json" \
-d '{"command":"start"}' | jq .
# Cleanup
echo "[10/10] Cleaning up..."
curl -s -X DELETE http://localhost:8080/api/v3/process/$PROCESS_ID \
-u admin:admin >/dev/null
docker stop restreamer-test
echo ""
echo "=========================================="
echo " Test suite completed successfully!"
echo "=========================================="chmod +x scripts/test-polyemesis.sh
./scripts/test-polyemesis.shUse this checklist for pre-release validation:
- Plugin installs correctly
- Dock appears in View menu
- No errors on first launch
- Settings file created correctly
- Can connect to local Restreamer
- Can connect to remote Restreamer
- HTTPS connections work
- Invalid credentials handled gracefully
- Connection persists across restarts
- Can create profiles
- Can configure all profile settings
- Can add destinations (all service types)
- Can edit destinations
- Can remove destinations
- Can duplicate profiles
- Can delete profiles
- Settings persist correctly
- Can start single profile
- Can stop single profile
- Can start all profiles
- Can stop all profiles
- Profile states transition correctly
- Buttons enable/disable properly
- Process state updates
- Metrics display correctly
- Uptime counter increments
- CPU/memory stats realistic
- Frame counts update
- Bitrate displayed
- Invalid stream keys detected
- Network failures handled
- Server unavailable handled
- Auto-reconnect works
- Error messages user-friendly
- Dark theme looks good
- Light theme looks good
- Window resizing works
- Tooltips helpful
- Tab navigation logical
- Context menus work
- No memory leaks (24h test)
- CPU usage reasonable
- Multiple profiles work
- UI remains responsive
- Passwords not in plaintext
- Stream keys masked
- TLS connections work
- File permissions correct
- macOS (Intel)
- macOS (Apple Silicon)
- Windows 10/11
- Linux (Ubuntu/Fedora)
Date: YYYY-MM-DD OBS Version: X.X.X Plugin Version: X.X.X OS: macOS/Windows/Linux Restreamer Version: X.X.X
| Test ID | Test Name | Status | Notes |
|---|---|---|---|
| 1.1 | Initial Connection | ✅ PASS | Connected in 2.3s |
| 1.2 | Invalid Credentials | ✅ PASS | Error displayed correctly |
| 2.1 | Create Profile | ✅ PASS | Profile created successfully |
| 3.1 | Start Profile | ❌ FAIL | Timeout after 30s |
| 3.2 | Monitor Stream | FPS metric not updating |
Issues Found:
- Profile start timeout: Server returned 500 error. Needs investigation.
- FPS metric: Value stays at 0 despite active stream. Check API polling.
Performance Metrics:
- Memory usage: 45MB (idle) → 120MB (5 active streams)
- CPU usage: 2% (idle) → 15% (5 streams)
- UI response time: <100ms for all actions
Run before every git commit:
# Quick smoke test
./scripts/test-polyemesis.sh
# Build test
cmake --build build-test
# Check for common issues
grep -r "TODO\|FIXME" src/Run before version bump:
- Full manual checklist
- All automated tests
- 24-hour stability test
- Cross-platform testing
- Security audit
- Monitor GitHub issues for bug reports
- Check user feedback on forums/Discord
- Track crash reports (if telemetry implemented)
- OBS Studio: https://obsproject.com/download
- Restreamer: https://datarhei.github.io/restreamer/
- Postman/curl: API testing
- jq: JSON parsing for scripts
- Valgrind: Memory leak detection (Linux)
- Instruments: Performance profiling (macOS)
- Restreamer API Docs: https://docs.datarhei.com/
- OBS Plugin Docs: https://obsproject.com/docs/plugins.html
- Qt Testing: https://doc.qt.io/qt-6/qtest-overview.html
If you find bugs or want to add test cases:
- Document the scenario in this file
- Provide reproduction steps (exact button clicks)
- Include expected vs actual results
- Attach logs if possible
- Submit GitHub issue with "test" label
Last Updated: 2025-11-09 Maintained By: OBS Polyemesis Development Team