I was having huge problems getting my selenium tests to run on CircleCI.

I tried to be really smart and launch an xvfb/selenium/webdriver docker container on their infrastructure which would then be used to run my selenium tests. This worked beautifully in a local Vagrant VM, but would fail for some reason on the CircleCI infrastructure.

**It turns out I was trying to be too clever for CircleCI. **

They run an xvfb screen by default on port :99, which is why my selenium node would silently fail.

To get my tests running i had to replace

@given('I have a web browser')
def browser():
    return webdriver.Remote(
        command_executor='http://127.0.0.1:4444/wd/hub',
        desired_capabilities=DesiredCapabilities.CHROME) with:

@given('I have a web browser')
def browser():
    try:
        return webdriver.Remote(
            command_executor='http://127.0.0.1:4444/wd/hub',
            desired_capabilities=DesiredCapabilities.CHROME)
    except:
        return webdriver.Chrome()

This setup runs nicely on my local vagrant, and on CircleCI.


Context managers are awesome:

I used to have lots of content functions like this:

def launch_celery():
    local('cd backendfail && celery -A settings worker --loglevel=INFO &')  # this is probably really bad
def kill_celery():
    local('killall celery') Which I used like this:

def coverage():
    launch_celery()
    launch_runserver()
    launch_selenium()
    local('coverage -m py.test backendfail/tests')
    kill_celery()
    kill_runserver()
    kill_selenium()

This was ugly because when coverage failed, celery wouldnt be killed and ruin my further tests.

Context managers are generators used with the with statement:

@contextmanager
def celery():
    local('cd backendfail && celery -A settings worker --loglevel=INFO &')  # this is much better
    yield
    local('killall celery')  # this is still pretty bad The `yield` statement passes control to the inner block of a `with` statement.

With context managers I can now do:

def coverage():
    with celery(), runserver(), selenium():
        local( r'coverage run -m py.test backendfail/tests')

This saves a lot of typing definitions and cleans up automatically, even if coverage fails.

Awesome.