Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Phpunit Selenium Laravel Package

phpunit/phpunit-selenium

PHPUnit-Selenium provides a Selenium2TestCase for running end-to-end browser tests with Selenium 2 in PHPUnit. Install via Composer and use version lines aligned to PHPUnit/PHP (e.g., 9.x for PHPUnit 9 on PHP 7.3+).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev phpunit/phpunit-selenium
    

    Ensure compatibility with your PHPUnit version (e.g., 9.x for PHPUnit 9.x + PHP 7.3+).

  2. Configure Selenium Server:

    • Download Selenium Server (e.g., selenium-server-standalone-<version>.jar).
    • Start it locally or via Docker:
      java -jar selenium-server-standalone-*.jar
      
      Or with Docker:
      docker run -d -p 4444:4444 selenium/standalone-firefox
      
  3. First Test Case: Extend Selenium2TestCase in your test file:

    use Facebook\WebDriver\Remote\RemoteWebDriver;
    use Facebook\WebDriver\WebDriverBy;
    use Facebook\WebDriver\WebDriverExpectedCondition;
    use PHPUnit\Extensions\Selenium2TestCase;
    
    class ExampleTest extends Selenium2TestCase
    {
        protected function setUp()
        {
            $host = 'http://localhost:4444/wd/hub';
            $this->setBrowserUrl('https://example.com');
            $this->setBrowser('firefox');
            $this->createSession($host);
        }
    
        public function testTitle()
        {
            $this->url('https://example.com');
            $this->assertEquals('Example Domain', $this->getTitle());
        }
    }
    
  4. Run Tests:

    ./vendor/bin/phpunit path/to/ExampleTest
    

Where to Look First


Implementation Patterns

Core Workflows

1. Test Setup/Teardown

  • Override setUp() to initialize the browser session:
    protected function setUp()
    {
        $this->setBrowser('chrome');
        $this->createSession('http://localhost:4444/wd/hub');
    }
    
  • Override tearDown() to close sessions:
    protected function tearDown()
    {
        $this->quit();
    }
    

2. Page Object Pattern

Encapsulate interactions in reusable classes:

class LoginPage
{
    private $driver;

    public function __construct(RemoteWebDriver $driver)
    {
        $this->driver = $driver;
    }

    public function login($username, $password)
    {
        $this->driver->findElement(WebDriverBy::name('username'))->sendKeys($username);
        $this->driver->findElement(WebDriverBy::name('password'))->sendKeys($password);
        $this->driver->findElement(WebDriverBy::cssSelector('button[type="submit"]'))->click();
    }
}

Usage in test:

$loginPage = new LoginPage($this->driver);
$loginPage->login('user', 'pass');

3. Dynamic Waits

Use Selenium’s built-in waits for flaky elements:

$this->waitUntil(
    WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('dynamic-element')),
    'Element not found'
);

4. Cross-Browser Testing

Parameterize tests by browser:

/**
 * @dataProvider browserProvider
 */
public function testAcrossBrowsers($browser)
{
    $this->setBrowser($browser);
    $this->createSession('http://localhost:4444/wd/hub');
    // Test logic...
}

public function browserProvider()
{
    return [
        ['firefox'],
        ['chrome'],
        ['edge'],
    ];
}

Integration Tips

Laravel-Specific

  1. Service Container Binding: Bind the WebDriver instance to Laravel’s container for dependency injection:

    // In a service provider
    $this->app->bind(RemoteWebDriver::class, function () {
        return new RemoteWebDriver('http://localhost:4444/wd/hub', DesiredCapabilities::firefox());
    });
    
  2. Test Environment: Use Laravel’s .env for Selenium config:

    SELENIUM_HOST=http://selenium:4444/wd/hub
    SELENIUM_BROWSER=chrome
    

    Load in setUp():

    $this->createSession(config('selenium.host'));
    $this->setBrowser(config('selenium.browser'));
    
  3. Dockerized Selenium: Use Docker Compose for isolated testing:

    # docker-compose.yml
    services:
      selenium:
        image: selenium/standalone-chrome
        ports:
          - "4444:4444"
    

    Start with:

    docker-compose up -d
    

CI/CD

  • GitHub Actions Example:
    jobs:
      test:
        runs-on: ubuntu-latest
        services:
          selenium:
            image: selenium/standalone-chrome
            ports:
              - 4444:4444
        steps:
          - uses: actions/checkout@v2
          - run: composer install
          - run: ./vendor/bin/phpunit --testdox-html report.html
    

Gotchas and Tips

Pitfalls

  1. Session Management:

    • Issue: Forgetting to call $this->quit() in tearDown() can leave zombie sessions.
    • Fix: Always include $this->quit() or use a trait to enforce cleanup.
  2. Browser Compatibility:

    • Issue: Some browsers (e.g., Firefox) require specific capabilities or versions.
    • Fix: Use DesiredCapabilities for fine-grained control:
      $capabilities = DesiredCapabilities::firefox();
      $capabilities->setCapability('marionette', true); // For Firefox GeckoDriver
      $this->createSession('http://localhost:4444/wd/hub', $capabilities);
      
  3. Flaky Tests:

    • Issue: Network latency or slow page loads cause intermittent failures.
    • Fix: Use explicit waits (e.g., waitUntil) instead of sleep().
  4. Headless Mode:

    • Issue: Tests pass locally but fail in CI (e.g., missing Xvfb in headless environments).
    • Fix: Configure headless browsers explicitly:
      $capabilities = DesiredCapabilities::chrome();
      $capabilities->setCapability('goog:chromeOptions', [
          'args' => ['headless', 'disable-gpu']
      ]);
      
  5. Resource Leaks:

    • Issue: Long-running tests consume excessive memory.
    • Fix: Limit test scope and use setBrowserUrl() to avoid full page reloads.

Debugging Tips

  1. Logs and Output:

    • Enable verbose logging:
      $this->setBrowserLogLevel(\Facebook\WebDriver\WebDriverCapabilities::LOG_DEBUG);
      
    • Check Selenium Server logs for errors.
  2. Screenshots on Failure: Automate screenshot capture in tearDown():

    protected function tearDown()
    {
        if ($this->hasFailed()) {
            $this->takeScreenshot('screenshot_' . $this->getName() . '.png');
        }
        $this->quit();
    }
    
  3. Remote Debugging: Attach Chrome DevTools to a Selenium session:

    $capabilities->setCapability('goog:chromeOptions', [
        'debuggerAddress' => '127.0.0.1:9222'
    ]);
    

Extension Points

  1. Custom Assertions: Extend Selenium2TestCase to add domain-specific assertions:

    class CustomSeleniumTestCase extends Selenium2TestCase
    {
        protected function assertElementVisible($locator)
        {
            $this->assertTrue(
                $this->isElementVisible($locator),
                "Element '$locator' is not visible."
            );
        }
    }
    
  2. Hooks for CI: Add pre/post-test hooks for CI tools:

    class CIAwareTestCase extends Selenium2TestCase
    {
        protected function setUp()
        {
            if (getenv('CI')) {
                $this->setBrowser('chrome');
                $this->createSession('http://selenium:4444/wd/hub');
            } else {
                // Local setup...
            }
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor