Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a PHPUnit test appears to do nothing with PhantomJS, first find the last WebDriver command that completed and identify which process is still alive. The pause may be an explicit or implicit wait for a page condition, a PhantomJS/GhostDriver failure, a PHP Selenium client waiting for a response, or PHPUnit blocked while cleaning up a child process. Treat those as separate failure layers, collect versions and logs, then reduce the test to a small cross-browser case.

Start with a reproducible baseline

Do not increase every timeout before you know what is waiting. From the same shell, account, container and working directory that PHPUnit uses, record:

  • PHP and PHPUnit versions.
  • The PHP Selenium/WebDriver binding version, Selenium server version and browser-driver versions.
  • The exact PhantomJS executable path and version.
  • Operating system, CI or local environment, proxy/TLS settings and test timeout values.
  • The final PHPUnit output and the last WebDriver command that completed.
  • PHPUnit output, PhantomJS/GhostDriver output, and the process tree at the moment of the stall.

The PHP WebDriver project’s documentation covers Selenium 2.x, 3.x and 4.x combinations; check that matrix against the versions actually installed rather than assuming that a binding, server and browser driver are interchangeable.

Find the process that is still alive

When the test stops, inspect the process list or CI job diagnostics. A live PhantomJS process suggests a browser or page-side problem. A live PHPUnit process with no browser suggests the PHP client or test code is waiting. A PHP child with a full pipe can indicate process-isolation I/O, while an exited browser with a waiting client points to a driver or teardown problem. This single observation prevents unrelated fixes from being mixed together.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Test synchronization before changing timeouts

Selenium’s official troubleshooting guidance states: “The most common Selenium-related error is a result of poor synchronization.” A page can be visually present while its title, element, AJAX result or network request is not ready. A fixed sleep can also finish too early or make every run unnecessarily slow.

Identify the condition that the test really needs

  • Navigation: wait for the expected URL or document state.
  • Element readiness: wait for presence, visibility or enabled state.
  • Asynchronous JavaScript: wait for the callback or a page flag to become true.
  • Network-backed content: wait for the result element, not an arbitrary delay.
  • Teardown: wait for the session to close and the browser process to exit.

Replace an unbounded or guessed delay with an explicit wait and a bounded timeout. In PHP WebDriver, the exact wait API depends on the binding version, so use the method documented by that version and make timeout failures report the condition and locator. Keep implicit waits conservative; combining a long implicit wait with explicit waits can multiply delays and make a stall look random.

Make the wait observable

Log immediately before and after navigation, element lookup, script execution and session deletion. Include the URL, locator, timeout and elapsed time. If the “before” message is the last line, the call itself is blocked. If both messages appear but PHPUnit does not continue, investigate assertion code, teardown or process handling instead of the page.

Verify the PhantomJS executable and enable WebDriver logs

Multiple PhantomJS installations are a documented source of confusion. Verify the binary that the test process resolves, not merely the one you ran interactively. Run the path and version check as the same user and inside the same CI image or container:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
which phantomjs
phantomjs --version
readlink -f "$(which phantomjs)"

On Windows, use the equivalent command that resolves the executable (for example, where phantomjs) and print the resolved path from the test setup. Compare local and CI results. PhantomJS’s command-line documentation describes the 2.1.1 line and its WebDriver mode; that documentation is historical, not evidence that 2.1.1 is a current browser.

Rank #2
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Start GhostDriver with a logfile

When PhantomJS is launched directly, enable its documented WebDriver options:

phantomjs --webdriver=4444 
  --webdriver-logfile=/tmp/phantomjs-webdriver.log 
  --webdriver-loglevel=DEBUG

Use a writable path in CI and archive the file as a build artifact. If your launcher owns the process, pass the same options through that launcher rather than starting a second server. Check the log for session creation, the last command received, navigation errors and an orderly or abnormal shutdown.

Capture page-side errors when needed

PhantomJS’s page API provides an onError callback for JavaScript exceptions and callbacks such as onResourceRequested for network diagnostics. Its remote debugger can be enabled with --remote-debugger-port. These are legacy tools, so expect differences from current browser-devtools workflows; the useful goal is to learn whether the page throws an exception or leaves a request unresolved before the WebDriver call returns.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Reduce the test to a minimal case

Create one test that starts a session, opens a stable URL, performs one assertion and quits in a finally block. Remove application login, large fixtures, parallel execution and unrelated JavaScript. Log each boundary. A minimal case tells you whether the stall occurs during session creation, navigation, an element command, script execution or teardown.

Run the same scenario in another browser

Run that small scenario with a supported Chrome or Firefox driver while keeping the Selenium client, server, URL and test code constant. Selenium recommends trying commands in multiple browsers to help distinguish driver problems.

  • Only PhantomJS stalls: investigate GhostDriver behavior, unsupported WebDriver commands, page JavaScript that PhantomJS cannot run, and TLS or network differences.
  • Every browser stalls at the same action: investigate application readiness, server responses, synchronization and the test itself.
  • Session creation fails in all browsers: check Selenium server, binding, driver paths, ports and version compatibility.

Do not infer a single root cause from the historic wording “Firefox works, but PhantomJS does nothing.” Without the versions, command, logs and reproduction, that wording only identifies a symptom.

Check PHPUnit and child-process cleanup

Observe whether PHPUnit is blocked around a child process. PHPUnit issue #5993 reports an indefinite hang with process-isolated tests in a specific environment—PHPUnit 10.5.36 and PHP 8.3.12—when a child emits a large amount of stderr. The report identifies a blocking stream read. It is a diagnostic lead, not proof that PhantomJS is responsible.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Look for pipe and isolation symptoms

  • Run the test without process isolation as a comparison, if isolation is not required.
  • Temporarily redirect or reduce verbose child stderr and compare behavior.
  • Capture stdout and stderr without waiting on one stream while the other can fill.
  • Check whether a PHP child remains after the browser exits.

Keep this experiment narrow and restore the project’s intended isolation settings after identifying the layer at fault.

Always close the session

Put WebDriver shutdown in a finally block so assertion failures do not leave PhantomJS running. Verify that the driver process exits and that the client receives a response. A historical Selenium issue shows that a client can wait about a minute before reporting a driver that exited immediately; that symptom warns against treating a long timeout as proof that the page was merely slow.

Use logs to classify the stall

Last known event Likely layer to inspect first Next evidence
No session-created message PhantomJS launch, port, executable or Selenium connection Resolved binary path, version, process stderr and listening port
Session exists; navigation never returns Page load, TLS/network, GhostDriver or an unsupported page feature WebDriver log, resource callbacks, URL and browser comparison
Navigation returns; element wait never completes Synchronization, selector or application readiness Explicit-wait condition, locator, page HTML and timeout log
Commands finish; PHPUnit remains alive Assertion, teardown or child-process I/O Process tree, stderr volume and session-delete log
Browser exits; client waits Driver disconnect or delayed error reporting Driver/GhostDriver exit log and client timeout

Common fixes and their limits

“Just raise the timeout”

A larger bounded timeout can accommodate a known slow environment, but it cannot fix a selector that never appears, a dead browser process or a blocked pipe. First make the failure observable with an explicit condition and logs.

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers

“Add a sleep after every click”

This hides readiness bugs and creates slow, flaky suites. Wait for the result of the click: a URL change, visible element, enabled control or application-specific completion marker.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

“Reinstall PhantomJS”

Reinstallation is useful only after you prove which binary PHPUnit invokes. A second installation can leave PATH precedence unchanged or create a local/CI mismatch.

“The page works manually, so WebDriver is fine”

Manual browsing does not reproduce the same user agent, viewport, TLS stack, timing or JavaScript engine. Compare browser logs and the minimal automated case.

Decide whether to repair or migrate

PhantomJS is a legacy choice: its GitHub repository is archived and read-only. A Selenium issue opened in 2018 records PhantomJS deprecation in Selenium 3.8.1 and recommends headless Chrome or Firefox. If the suite is maintained, migration is usually the more durable path, but verify the project’s own browser and driver compatibility before changing it.

Decision question If the answer is yes If the answer is no
Does the stall occur only in PhantomJS? Prioritize GhostDriver, unsupported commands and page compatibility. Prioritize synchronization, application responses and test code.
Are the client, server and driver versions documented as compatible? Keep version mismatch lower on the list. Align versions before deeper debugging.
Can current CI install an alternative browser and driver? Prototype headless Chrome or Firefox with the minimal test. Plan the CI image and driver change as part of migration.
Does the project still need PhantomJS-specific behavior? Document the legacy constraint and isolate it. Schedule migration and remove the obsolete dependency.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is to capture a page image or PDF rather than exercise PHPUnit interactions, ScreenshotNeo makes one request to the URL. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

See the ScreenshotNeo documentation for authentication and options. A direct call is:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account to try it.

Further options when a screenshot is the actual requirement

  • Full-page capture loads lazy images; you can capture one CSS-selected element, choose dark mode, use 12 device presets or any viewport, and set retina scale.
  • PDF capture supports paper size, margins, landscape mode and page ranges.
  • HTML/CSS-to-image, custom CSS and JavaScript, pre-capture clicks, hidden selectors, waits for selectors/delays/network idle, and blocking ads, trackers, requests or resource types cover common rendering cases.
  • Custom headers, cookies, user agents, Authorization, timezone and geolocation handle authenticated or localized pages.
  • Transparent backgrounds, image resizing, configurable-TTL caching, signed public image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification are available.

These capabilities replace browser orchestration for capture workloads; they do not replace Selenium when the test must click through application behavior and assert interactions.

FAQ

Is every PhantomJS stall a synchronization bug?

No. Synchronization is a common Selenium failure source, but the executable, GhostDriver, network, PHPUnit teardown and child-process I/O can all produce the same appearance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I keep PhantomJS for a stable legacy suite?

Only with an explicit compatibility and maintenance reason. The project is archived, so pin the environment, preserve logs and plan a supported-browser migration.

What is the first fact to collect from CI?

The last completed WebDriver command plus the resolved PhantomJS path and version. Together they identify whether the pause is before session creation, during a browser command or after the browser has already exited.

Frequently Asked Questions

Can a failed page load be mistaken for a PHPUnit hang?

Yes. If the client waits for a navigation response, a network or driver failure can leave PHPUnit appearing idle. WebDriver and PhantomJS logs distinguish that from a test-process block.

When is ScreenshotNeo preferable to Selenium?

Use ScreenshotNeo for reproducible screenshots or PDFs when you do not need interactive assertions. Keep Selenium for behavioral tests that must operate the application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The Bottom Line

Find the last completed command, identify the live process, replace guessed sleeps with bounded explicit waits, verify the exact PhantomJS binary, preserve GhostDriver logs, compare another browser, and inspect PHPUnit child-process I/O. Because PhantomJS is archived, use the evidence from that minimal case to plan a supported-browser migration rather than extending an opaque timeout indefinitely.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.