Understanding the Sahi Pro Architecture
Core Components
- Controller: The browser extension or proxy-based interface that injects Sahi scripts into target applications.
- Playback Engine: Executes scripts line by line while synchronizing DOM access using wait conditions and retries.
- Accessors: JavaScript-based mechanisms for interacting with web elements, including _textbox(), _link(), and _button().
- Suite Runner: Executes grouped test cases with reporting and logging support.
Execution Modes
Sahi Pro supports playback via browser automation, batch execution via command-line interfaces, and integrations with CI/CD tools like Jenkins. Each mode introduces its own challenges due to differences in environment setup, timing, and network constraints.
Common Enterprise-Scale Failures
1. Intermittent Element Not Found Errors
These typically arise when dynamic content renders asynchronously or the page uses complex shadow DOM or iframes. Sahi’s default timeout (10s) may be insufficient in slower test environments.
2. Inconsistent Behavior Between Local and CI Execution
Tests that pass locally but fail in Jenkins or other CI runners often result from differences in screen resolution, browser versions, or lack of GUI rendering support in headless environments.
3. Proxy Interference in Multi-Domain Tests
When testing apps that span subdomains or use CORS, Sahi’s proxy may misinject scripts or fail to record/access elements due to same-origin policy restrictions or certificate trust issues.
4. Performance Degradation in Large Test Suites
As the number of scripts increases, memory consumption and execution times grow significantly if browser sessions are not correctly managed or logs are not rotated.
5. Incomplete Reporting and Logging on Crashes
In rare cases, test runs may abort mid-suite without logging details if Sahi’s log directory lacks write permissions or if the JVM heap is exhausted without proper error trapping.
Step-by-Step Diagnostic Strategy
1. Enable Debug Logging
In sahi/userdata/config/userdata.properties: debug.mode=true debug.level=3
Then restart Sahi Pro controller. Review logs in userdata/logs/playback
.
2. Validate Accessor Targets
Use the Sahi Controller’s Accessor Viewer in both local and CI environments to confirm that dynamic IDs or attribute changes are handled using stable locators like _near()
or _contains()
.
3. Isolate Proxy Conflicts
In userdata/config/streamfilter.properties: exclude_hosts=*.cdn.com,*.analytics.com
This prevents script injection into 3rd-party or static resources that don't require automation.
4. Monitor JVM and OS Resources
On Linux/Unix: top ulimit -a jstat -gc $(pidof java)
Ensure sufficient heap allocation in sahi.bat
or sahi.sh
via JAVA_OPTS:
JAVA_OPTS=-Xmx1024m -Xms512m
5. Instrument CI/CD Jobs
In Jenkins or other tools, ensure the job includes:
export DISPLAY=:99 Xvfb :99 -screen 0 1280x1024x24 & $SAHI_HOME/bin/testrunner.sh sample.suite localhost 9999 chrome
Monitor stdout/stderr for Selenium or OS-level errors during test execution.
Best Practices to Improve Stability
- Use stable accessors: Favor semantic locators (_near, _row) over brittle ID-based ones.
- Leverage smart waits: Use
_wait()
and_waitFor()
strategically instead of fixed delays. - Modularize tests: Break scripts into reusable functions and components for better logging and isolation.
- Enable log rotation: Prevent file bloat by archiving old logs regularly.
- Lock versions: Fix browser and Sahi versions in CI to prevent surprise failures from auto-updates.
Code Example: Resilient Accessor Use
// Fragile version _setValue(_textbox("username"), "admin") // Resilient version _setValue(_textbox(_near("Username")), "admin")
Using contextual locators ensures robustness against dynamic IDs.
Advanced Debugging Techniques
Heap Dump Analysis
Enable JVM heap dumps on out-of-memory errors by setting:
JAVA_OPTS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/sahi_heap.hprof"
Analyze dumps using Eclipse MAT to identify memory leaks from unclosed browser sessions or large DOM captures.
CI Parallel Execution Debugging
Ensure no port conflicts by assigning unique playback ports to each CI job:
testrunner.sh suite1.suite localhost 9999 chrome testrunner.sh suite2.suite localhost 9998 chrome
Set environment variables dynamically in the pipeline to manage this.
Conclusion
While Sahi Pro excels in test automation for complex web apps, troubleshooting failures at scale requires an architectural understanding of its proxy model, execution layers, and JavaScript-based element accessors. Inconsistent behavior across environments, CI instability, and element flakiness can be resolved through disciplined diagnostics, JVM tuning, smart wait strategies, and CI orchestration best practices. A modular, log-driven, and environment-aware approach to Sahi Pro testing enables higher test reliability and faster recovery from transient issues.
FAQs
1. Why do Sahi tests fail only in Jenkins but pass locally?
Jenkins often runs in headless mode without GUI rendering, which can impact timing, font metrics, or dynamic layout. Using Xvfb or enabling GUI emulation resolves most rendering-dependent failures.
2. How can I reduce flaky element locator failures?
Use context-based accessors like _near() or _under() instead of static IDs, which often change dynamically. Also, use _waitFor() to ensure element readiness before interaction.
3. Is it safe to exclude hosts in streamfilter.properties?
Yes, especially for domains that do not require automation or interfere with playback. Be cautious not to exclude core app domains or SSO providers.
4. Can Sahi Pro be used in parallel test execution?
Yes, but each instance must use separate ports and browser profiles. Manage port assignment via pipeline environment variables to avoid collisions.
5. What causes memory bloat during large suite runs?
Unclosed browser instances, extensive DOM snapshots, or large logs can cause heap exhaustion. Monitor JVM memory usage and rotate logs periodically to mitigate this.