Package: externaltestserver
# `django-externaltestserver`[![PyPI Version](https://img.shields.io/pypi/v/https://pypi.python.org/pypi/django-externaltestserver.svg?style=flat-square)![PyPI Python Versions](https://img.shields.io/pypi/pyversions/django-externaltestserver.svg?style=flat-square)](https://pypi.python.org/pypi/django-externaltestserver)[![Travis branch](https://img.shields.io/travis/saulshanabrook/django-externaltestserver/master.svg?style=flat-square)](https://travis-ci.org/saulshanabrook/django-externaltestserver)<!-- MarkdownTOC depth=0 autolink=true -->- [How?][how]- [Why?][why]- [External Server][external-server]- [Docker][docker]- [Problem][problem]- [Solution][solution]- [Development][development]<!-- /MarkdownTOC -->## How?1. `pip install django-externaltestserver`.2. Set `EXTERNAL_TEST_SERVER` in your settings3. Change test cases to inherit from`externaltestserver.ExternalLiveServerTestCase` instead of`LiveServerTestCase`.4. (optional) Add `externaltestserver` to `INSTALLED_APPS` to run`python manage.py testserver <port> [--static]` in another process.## Why?### External ServerWe have a CI system that pushes to a staging server after all tests pass.We wanted to re-run our selenium test against the staging server, to makesure there are no regressions moving from a dev to a staging environment.To do this, we just have to set the `EXTERNAL_TEST_SERVER`setting to our staging server (like `http://magicapp-staging.herokuapp.com/`)and make sure our integration tests inherit from `externaltestserver.ExternalLiveServerTestCase`so that they get the correct `live_server_url`.### Docker#### ProblemTesting Selenium in Django with Docker is[not obvious](http://stackoverflow.com/questions/32408429/running-django-tests-with-selenium-in-docker).The problem is that there is a circular dependency between the testingcontainer and the selenium container. The test container needs to accessselenium in order to send commands and recieve responses. The seleniumcontainer needs to access the testing container, in order to hit the server.![diagram of old process](./images/old.jpg)We might hope we could represent this relation this in our `docker-compose.yml````yamldb:image: postgrestest:build: .command: python manage.py testlinks:- db- seleniumselenium:image: selenium/standalone-chromeports:- "4444:4444"- "5900:5900"links:- test```But alas `ERROR: Circular import between test and selenium and db`.I was previously using[an alternative solution](https://github.com/docker/compose/issues/1991#issuecomment-138139493),by placing the the `test` container in the same network as the `selenium`container, so that they could access each other.```yamldb:image: postgrestest:build: .command: python manage.py testlinks:- dbnet: "container:selenium"selenium:image: selenium/standalone-chromeports:- "4444:4444"- "5900:5900"```This stopped working with Docker Compose 1.5.0 / Docker 1.9.0 with`ERROR: Conflicting options: --net=container can't be used with links. This would result in undefined behavior`.#### SolutionThe simplist solution to me seemed to be to break up the test command intotwo seperate Docker containers. One would handle serving the server, the otherwould just run the tests.![diagram of new process](./images/new.jpg)That way there are no cyclical dependencies.```yamldb:image: postgres:9.5test:build: .# sleep for https://github.com/docker/compose/issues/374#issuecomment-156546513command: bash -c "sleep 5; python manage.py test --keepdb"links:- db- seleniumenvironment:- EXTERNAL_TEST_SERVER=http://testserver:8000/- SELENIUM_HOST=http://selenium:4444/wd/hubselenium:image: selenium/standalone-chrome:2.48.2links:- testservertestserver:build: .# sleep for https://github.com/docker/compose/issues/374#issuecomment-156546513command: bash -c "sleep 5; python manage.py testserver 8000 --static"expose:- "8000"links:- db```Then just make sure we are picking up the host in the settings:```python# settings.pyimport osEXTERNAL_TEST_SERVER = os.environ.get('EXTERNAL_TEST_SERVER', None)```And that your tests are inheriting from `externaltestserver.ExternalLiveServerTestCase`and accesing the right selenium server:```python# test_integration.pyimport osfrom selenium import webdriverfrom selenium.webdriver.common.desired_capabilities import DesiredCapabilitiesfrom externaltestserver import ExternalLiveServerTestCasefrom items.models import Itemclass IntegrationTest(ExternalLiveServerTestCase):def setUp(self):self.browser = webdriver.Remote(command_executor=os.environ['SELENIUM_HOST'],desired_capabilities=DesiredCapabilities.CHROME)def test_item_count(self):Item.objects.create()self.browser.get(self.live_server_url)self.assertIn("1", self.browser.page_source)```Then you can run all the tests with `docker-compose run test`.## DevelopmentFirst choose what python and django versions you wanna test on:```bashsed -e 's/${PYTHON_VERSION}/3.5/g' -e 's/${DJANGO_VERSION}/1.8/g' Dockerfile.tmpl  > Dockerfile```Then run the tests:```bashdocker-compose run test```To deploy a new version:```python setup.py publishgit tag <version number>git push --tags```