Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify integration test workflow fixes #1914 #2354

Merged
merged 10 commits into from
Mar 17, 2020
5 changes: 4 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ jobs:
name: Run integration tests
command: |
sudo chown -R ubuntu tests/
cp .env.integration .env
cp .env.sample .env
make refresh
make up_detached
make integration_test
make kill
- store_artifacts:
path: tests/integration/integration-test.html

Expand Down
4 changes: 2 additions & 2 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
BUGZILLA_API_KEY=
BUGZILLA_CC_LIST=
BUGZILLA_HOST=
BUGZILLA_HOST=https://bugzilla.allizom.org/
DB_HOST=db
DB_NAME=postgres
DB_PASS=postgres
DB_USER=postgres
DEBUG=True
DELIVERY_CONSOLE_HOST=
DS_ISSUE_HOST=https://jira.mozilla.com/browse/
DS_ISSUE_HOST=https://jira.example.com/browse/
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
EMAIL_HOST=
EMAIL_HOST_PASSWORD=
Expand Down
50 changes: 23 additions & 27 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ WAIT_FOR_DB = /app/bin/wait-for-it.sh db:5432 --

COMPOSE = docker-compose -f docker-compose.yml
COMPOSE_TEST = docker-compose -f docker-compose-test.yml
COMPOSE_INTEGRATION = docker-compose -f docker-compose.yml -f docker-compose.integration-test.yml
COMPOSE_FULL = docker-compose -f docker-compose.yml -f docker-compose-full.yml

PYTHON_TEST = pytest -vvvv --cov --cov-report term-missing --show-capture=no
PYTHON_TEST_FAST = python manage.py test -v 3 --parallel
Expand Down Expand Up @@ -70,21 +72,26 @@ checkfast: test_build
compose_build: build ssl
$(COMPOSE) build

compose_kill:
compose_stop:
$(COMPOSE) kill
$(COMPOSE_INTEGRATION) kill

compose_rm:
$(COMPOSE) rm -f
$(COMPOSE) rm -f -v
$(COMPOSE_INTEGRATION) rm -f -v

volumes_rm:
docker volume ls -q | xargs docker volume rm
docker volume ls -q | xargs docker volume rm -f | echo

kill: compose_kill compose_rm volumes_rm
kill: compose_stop compose_rm volumes_rm
echo "All containers removed!"

up: compose_kill compose_build
up: compose_stop compose_build
$(COMPOSE) up

up_detached: compose_stop compose_build
$(COMPOSE) up -d

generate_docs: compose_build
$(COMPOSE) run app sh -c "$(GENERATE_DOCS)"

Expand Down Expand Up @@ -128,43 +135,32 @@ bash: compose_build

refresh: kill migrate load_locales_countries load_dummy_experiments

COMPOSE_FULL = docker-compose -f docker-compose.yml -f docker-compose-full.yml

# experimenter + delivery console + normandy stack
compose_build_all: build ssl
$(COMPOSE_FULL) build

up_all: compose_build_all
$(COMPOSE_FULL) up

kill_all: kill
$(COMPOSE_FULL) kill
$(COMPOSE_FULL) -v rm

normandy_shell: compose_build_all
$(COMPOSE_FULL) run normandy ./manage.py shell

COMPOSE_INTEGRATION = docker-compose -p experimenter_integration -f docker-compose.yml -f docker-compose.integration-test.yml

# integration tests
integration_kill:
$(COMPOSE_INTEGRATION) kill
$(COMPOSE_INTEGRATION) rm -f

integration_build: integration_kill ssl build
integration_build: compose_build
$(COMPOSE_INTEGRATION) build
$(COMPOSE_INTEGRATION) run app sh -c "$(WAIT_FOR_DB) python manage.py migrate;python manage.py load-countries;python manage.py loaddata ./fixtures/locales.json;python manage.py createsuperuser --username admin --email admin@example.com --noinput"

integration_shell: integration_build
$(COMPOSE_INTEGRATION) run firefox bash

integration_up_shell:
$(COMPOSE_INTEGRATION) run firefox bash

integration_up_detached: integration_build
$(COMPOSE_INTEGRATION) up -d

integration_up: integration_build
$(COMPOSE_INTEGRATION) up
integration_vnc_up: integration_build
$(COMPOSE_INTEGRATION) up vnc

integration_test_run: integration_build
$(COMPOSE_INTEGRATION) run firefox tox -c tests/integration
integration_vnc_up_detached: integration_build
$(COMPOSE_INTEGRATION) up -d vnc

integration_test: compose_kill integration_test_run integration_kill
echo "Firefox tests complete!"
integration_test: integration_build
$(COMPOSE_INTEGRATION) run firefox tox -c tests/integration
2 changes: 1 addition & 1 deletion app/experimenter/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
ALLOWED_HOSTS = [HOSTNAME]

if DEBUG:
ALLOWED_HOSTS += ["localhost"] # pragma: no cover
ALLOWED_HOSTS += ["localhost", "nginx"] # pragma: no cover

SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")

Expand Down
33 changes: 17 additions & 16 deletions docker-compose.integration-test.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
version: "3"

services:
app:
env_file: .env.integration

yarn:
command: ""

worker:
env_file: .env.integration

beat:
env_file: .env.integration

nginx:
env_file: .env.integration

firefox:
image: b4handjr/selenium-firefox:python3-latest
env_file: .env
volumes:
- .:/code
links:
- nginx
expose:
- "4444"
shm_size: 2g
networks:
- private_nw
- public_nw
vnc:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of having 2 services, we could just use the MOZ_HEADLESS env variable. If it is set then the tests would not be viewable through the vnc server.

image: b4handjr/selenium-firefox:python3-latest
env_file: .env
environment:
- DISABLE_HEADLESS=1
volumes:
- .:/code
links:
Expand All @@ -29,4 +30,4 @@ services:
shm_size: 2g
networks:
- private_nw
- public_nw
- public_nw
13 changes: 10 additions & 3 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

import pytest
import requests
from requests.packages.urllib3.util.retry import Retry
Expand All @@ -6,6 +8,11 @@
from pages.home import Home


@pytest.fixture
def ds_issue_host():
return os.environ["DS_ISSUE_HOST"]


@pytest.fixture
def capabilities(capabilities):
capabilities["acceptInsecureCerts"] = True
Expand All @@ -15,7 +22,7 @@ def capabilities(capabilities):
@pytest.fixture
def firefox_options(firefox_options):
"""Set Firefox Options."""
firefox_options.headless = True
firefox_options.headless = not bool(os.environ.get("DISABLE_HEADLESS"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can get rid of this line and just use the env variable MOZ_HEADLESS.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't get it to work quickly so I filed it as a followup:

#2389

firefox_options.log.level = "trace"
return firefox_options

Expand All @@ -32,13 +39,13 @@ def _verify_url(request, base_url):


@pytest.fixture
def fill_overview(selenium, base_url):
def fill_overview(selenium, base_url, ds_issue_host):
selenium.get(base_url)
home = Home(selenium, base_url).wait_for_page_to_load()
experiment = home.create_experiment()
experiment.name = "This is a test"
experiment.short_description = "Testing in here"
experiment.public_name = "Public Name"
experiment.public_description = "Public Description"
experiment.bugzilla_url = "https://jira.mozilla.com/browse/DS-123"
experiment.ds_issue_url = f"{ds_issue_host}DS-12345"
return experiment
6 changes: 3 additions & 3 deletions tests/integration/pages/experiment_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ def short_description(self, text=None):
return

@property
def bugzilla_url(self):
def ds_issue_url(self):
element = self.find_element(*self._ds_issue_url_locator)
return element.get_attribute("value")

@bugzilla_url.setter
def bugzilla_url(self, text=None):
@ds_issue_url.setter
def ds_issue_url(self, text=None):
element = self.find_element(*self._ds_issue_url_locator)
random_chars = "".join(random.choices(string.digits, k=6))
element.send_keys(f"{text}{random_chars}")
Expand Down
12 changes: 6 additions & 6 deletions tests/integration/test_create_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


@pytest.mark.nondestructive
def test_add_branch(base_url, selenium):
def test_add_branch(base_url, selenium, ds_issue_host):
"""Test adding a new branch."""
selenium.get(base_url)
home = Home(selenium, base_url).wait_for_page_to_load()
Expand All @@ -14,7 +14,7 @@ def test_add_branch(base_url, selenium):
experiment.short_description = "Testing in here"
experiment.public_name = "Public Name"
experiment.public_description = "Public Description"
experiment.bugzilla_url = "https://jira.mozilla.com/browse/DS-123"
experiment.ds_issue_url = f"{ds_issue_host}DS-12345"
exp_detail = experiment.save_btn()
exp_design = exp_detail.click_edit()
exp_design.input_firefox_pref_name("robot rock")
Expand All @@ -25,7 +25,7 @@ def test_add_branch(base_url, selenium):


@pytest.mark.nondestructive
def test_remove_branch(base_url, selenium):
def test_remove_branch(base_url, selenium, ds_issue_host):
"""Test removing a branch."""
selenium.get(base_url)
home = Home(selenium, base_url).wait_for_page_to_load()
Expand All @@ -34,7 +34,7 @@ def test_remove_branch(base_url, selenium):
experiment.short_description = "Testing in here"
experiment.public_name = "Public Name"
experiment.public_description = "Public Description"
experiment.bugzilla_url = "https://jira.mozilla.com/browse/DS-123"
experiment.ds_issue_url = f"{ds_issue_host}DS-12345"
exp_detail = experiment.save_btn()
exp_design = exp_detail.click_edit()
exp_design.input_firefox_pref_name("robot rock")
Expand All @@ -48,7 +48,7 @@ def test_remove_branch(base_url, selenium):


@pytest.mark.nondestructive
def test_duplicate_branch_name(base_url, selenium):
def test_duplicate_branch_name(base_url, selenium, ds_issue_host):
"""Test adding a branch with the same name as the control branch."""
selenium.get(base_url)
home = Home(selenium, base_url).wait_for_page_to_load()
Expand All @@ -57,7 +57,7 @@ def test_duplicate_branch_name(base_url, selenium):
experiment.short_description = "Testing in here"
experiment.public_name = "Public Name"
experiment.public_description = "Public Description"
experiment.bugzilla_url = "https://jira.mozilla.com/browse/DS-123"
experiment.ds_issue_url = f"{ds_issue_host}DS-12345"
exp_detail = experiment.save_btn()
exp_design = exp_detail.click_edit()
exp_design.input_firefox_pref_name("robot rock")
Expand Down
12 changes: 0 additions & 12 deletions tests/integration/test_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,6 @@ def test_overview_type_changes_correctly(base_url, selenium):
assert exp_type in experiment.experiment_type


@pytest.mark.nondestructive
def test_overview_owner_changes_correctly(base_url, selenium):
jaredlockhart marked this conversation as resolved.
Show resolved Hide resolved
"""Test changing experiment owner."""
selenium.get(base_url)
home = Home(selenium, base_url).wait_for_page_to_load()
experiment = home.create_experiment()
assert home.header.current_user in experiment.experiment_owner
owner = "admin"
experiment.experiment_owner = owner
assert owner in experiment.experiment_owner


@pytest.mark.nondestructive
def test_overview_engineering_owner_changes_correctly(base_url, selenium):
"""Test changing engineering owner."""
Expand Down