From 5cbaa240023b503e5ab712e9068ef093df7734bc Mon Sep 17 00:00:00 2001 From: Mike Edmunds Date: Sat, 28 Nov 2020 18:08:01 -0800 Subject: [PATCH] Move CI testing to GitHub Actions Related changes: * remove Travis-CI config; stop running tests on Travis * rename live integration test environment variables to all start with `ANYMAIL_TEST_` (simplifies tox config) --- .github/workflows/test.yml | 102 +++++++++++++++++++++++++++ .travis.yml | 71 ------------------- CHANGELOG.rst | 5 ++ README.rst | 6 +- docs/contributing.rst | 8 +-- runtests.py | 8 +-- setup.py | 2 +- tests/test_amazon_ses_integration.py | 22 +++--- tests/test_mailgun_integration.py | 24 +++---- tests/test_mailjet_integration.py | 14 ++-- tests/test_mandrill_integration.py | 10 +-- tests/test_postmark_integration.py | 12 ++-- tests/test_sendgrid_integration.py | 18 ++--- tests/test_sendinblue_integration.py | 10 +-- tests/test_sparkpost_integration.py | 10 +-- tox.ini | 11 +-- 16 files changed, 181 insertions(+), 152 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..858e196 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,102 @@ +name: test + +on: + push: + schedule: + # Weekly build (on branch main) every Thursday at 12:00 UTC. + # (Used to monitor compatibility with ESP APIs and other dependencies.) + - cron: '0 12 * * 4' + + +jobs: + test: + name: ${{ matrix.config.tox }} ${{ matrix.config.options }} + runs-on: ubuntu-18.04 + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + config: + - { tox: "lint,docs", python: 3.8 } + + # Anymail supports the same Python versions as Django, plus PyPy. + # https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django + + # Live API integration tests are only run on a few, representative Python/Django version + # combinations, to avoid rapidly consuming the testing accounts' entire send allotments. + + # Django 2.0: Python 3.5+ + - { tox: django20-py35-all, python: 3.5 } + - { tox: django20-py36-all, python: 3.6 } + - { tox: django20-pypy3-all, python: pypy3 } + # Django 2.1: Python 3.5, 3.6, or 3.7 + - { tox: django21-py35-all, python: 3.5 } + - { tox: django21-py36-all, python: 3.6 } + - { tox: django21-py37-all, python: 3.7 } + - { tox: django21-pypy3-all, python: pypy3 } + # Django 2.2: Python 3.5, 3.6, or 3.7 + - { tox: django22-py35-all, python: 3.5 } + - { tox: django22-py36-all, python: 3.6 } + - { tox: django22-py37-all, python: 3.7 } + - { tox: django22-pypy3-all, python: pypy3 } + # Django 3.0: Python 3.6, 3.7, or 3.8 + - { tox: django30-py36-all, python: 3.6 } + - { tox: django30-py37-all, python: 3.7 } + - { tox: django30-py38-all, python: 3.8 } + - { tox: django30-pypy3-all, python: pypy3 } + # Django 3.1: Python 3.6, 3.7, or 3.8 + - { tox: django31-py36-all, python: 3.6 } + - { tox: django31-py37-all, python: 3.7 } + - { tox: django31-py38-all, python: 3.8, options: run-live-tests } + - { tox: django31-pypy3-all, python: pypy3 } + # Django current development (direct from GitHub source) + - { tox: djangoDev-py37-all, python: 3.7, options: allow-failures } + # Install without optional extras (don't need to cover entire matrix) + - { tox: django31-py37-none, python: 3.7 } + - { tox: django31-py37-amazon_ses, python: 3.7 } + # Test some specific older package versions + - { tox: django22-py37-all-old_urllib3, python: 3.7 } + + steps: + - name: Get code + uses: actions/checkout@v2 + - name: Setup Python ${{ matrix.config.python }} + # Ensure matrix Python version is installed and available for tox + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.config.python }} + - name: Setup default Python + # Change default Python version back to something consistent + # for installing/running tox + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install tox + run: | + set -x + python --version + pip install tox + tox --version + - name: Test ${{ matrix.config.tox }} + run: | + tox --version + tox -e ${{ matrix.config.tox }} + continue-on-error: ${{ contains( matrix.config.options, 'allow-failures' ) }} + env: + CONTINUOUS_INTEGRATION: true + TOX_FORCE_IGNORE_OUTCOME: false + ANYMAIL_RUN_LIVE_TESTS: ${{ contains( matrix.config.options, 'run-live-tests' ) }} + ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID: ${{ secrets.ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID }} + ANYMAIL_TEST_AMAZON_SES_REGION_NAME: ${{ secrets.ANYMAIL_TEST_AMAZON_SES_REGION_NAME }} + ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY: ${{ secrets.ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY }} + ANYMAIL_TEST_MAILGUN_API_KEY: ${{ secrets.ANYMAIL_TEST_MAILGUN_API_KEY }} + ANYMAIL_TEST_MAILGUN_DOMAIN: ${{ secrets.ANYMAIL_TEST_MAILGUN_DOMAIN }} + ANYMAIL_TEST_MAILJET_API_KEY: ${{ secrets.ANYMAIL_TEST_MAILJET_API_KEY }} + ANYMAIL_TEST_MAILJET_SECRET_KEY: ${{ secrets.ANYMAIL_TEST_MAILJET_SECRET_KEY }} + ANYMAIL_TEST_MANDRILL_API_KEY: ${{ secrets.ANYMAIL_TEST_MANDRILL_API_KEY }} + ANYMAIL_TEST_POSTMARK_SERVER_TOKEN: ${{ secrets.ANYMAIL_TEST_POSTMARK_SERVER_TOKEN }} + ANYMAIL_TEST_POSTMARK_TEMPLATE_ID: ${{ secrets.ANYMAIL_TEST_POSTMARK_TEMPLATE_ID }} + ANYMAIL_TEST_SENDGRID_API_KEY: ${{ secrets.ANYMAIL_TEST_SENDGRID_API_KEY }} + ANYMAIL_TEST_SENDGRID_TEMPLATE_ID: ${{ secrets.ANYMAIL_TEST_SENDGRID_TEMPLATE_ID }} + ANYMAIL_TEST_SENDINBLUE_API_KEY: ${{ secrets.ANYMAIL_TEST_SENDINBLUE_API_KEY }} + ANYMAIL_TEST_SPARKPOST_API_KEY: ${{ secrets.ANYMAIL_TEST_SPARKPOST_API_KEY }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 531b4d2..0000000 --- a/.travis.yml +++ /dev/null @@ -1,71 +0,0 @@ -language: python -os: linux -dist: xenial - -branches: - # Only run builds on release branches. - # (Builds will *also* still run on pull requests; - # this avoids duplicate builds on the PR *branches*, too.) - only: - - main - - /^v\d+\.\d+(\.(\d|x)+)?(-\S*)?$/ - -env: - global: - # Let Travis report failures that tox.ini would normally ignore: - - TOX_FORCE_IGNORE_OUTCOME=false - -jobs: - include: - - python: 3.8 - env: TOXENV="lint,docs" - - # Anymail supports the same Python versions as Django, plus PyPy. - # https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django - - # Live API integration tests are only run on a few, representative Python/Django version - # combinations, to avoid rapidly consuming the testing accounts' entire send allotments. - - # Django 2.0: Python 3.5+ - - { env: TOXENV=django20-py35-all, python: 3.5 } - - { env: TOXENV=django20-py36-all, python: 3.6 } - - { env: TOXENV=django20-pypy3-all, python: pypy3 } - # Django 2.1: Python 3.5, 3.6, or 3.7 - - { env: TOXENV=django21-py35-all, python: 3.5 } - - { env: TOXENV=django21-py36-all, python: 3.6 } - - { env: TOXENV=django21-py37-all, python: 3.7 } - - { env: TOXENV=django21-pypy3-all, python: pypy3 } - # Django 2.2: Python 3.5, 3.6, or 3.7 - - { env: TOXENV=django22-py35-all, python: 3.5 } - - { env: TOXENV=django22-py36-all, python: 3.6 } - - { env: TOXENV=django22-py37-all, python: 3.7 } - - { env: TOXENV=django22-pypy3-all, python: pypy3 } - # Django 3.0: Python 3.6, 3.7, or 3.8 - - { env: TOXENV=django30-py36-all, python: 3.6 } - - { env: TOXENV=django30-py37-all, python: 3.7 } - - { env: TOXENV=django30-py38-all, python: 3.8 } - - { env: TOXENV=django30-pypy3-all, python: pypy3 } - # Django 3.1: Python 3.6, 3.7, or 3.8 - - { env: TOXENV=django31-py36-all, python: 3.6 } - - { env: TOXENV=django31-py37-all, python: 3.7 } - - { env: TOXENV=django31-py38-all RUN_LIVE_TESTS=true, python: 3.8 } - - { env: TOXENV=django31-pypy3-all, python: pypy3 } - # Django current development (direct from GitHub source main branch): - - { env: TOXENV=djangoDev-py37-all, python: 3.7 } - # Install without optional extras (don't need to cover entire matrix) - - { env: TOXENV=django31-py37-none, python: 3.7 } - - { env: TOXENV=django31-py37-amazon_ses, python: 3.7 } - # Test some specific older package versions - - { env: TOXENV=django22-py37-all-old_urllib3, python: 3.7 } - - allow_failures: - - env: TOXENV=djangoDev-py37-all - python: 3.7 - -cache: pip - -install: - - pip install tox - -script: - - tox diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1eff486..88b6cbd 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -37,6 +37,11 @@ Fixes started issuing a cryptic "No sending domain specified" error for this case; with this fix, Anymail will now treat it as an unsupported feature. +Other +~~~~~ + +* Move CI testing to GitHub Actions (and stop using Travis-CI). + v8.1 diff --git a/README.rst b/README.rst index 7d92cae..3569ed8 100644 --- a/README.rst +++ b/README.rst @@ -51,9 +51,9 @@ The package is released under the BSD license. .. END shared-intro -.. image:: https://travis-ci.org/anymail/django-anymail.svg?branch=main - :target: https://travis-ci.org/anymail/django-anymail - :alt: build status on Travis-CI +.. image:: https://github.com/anymail/django-anymail/workflows/test/badge.svg?branch=main + :target: https://github.com/anymail/django-anymail/actions?query=workflow:test+branch:main + :alt: build status in GitHub Actions .. image:: https://readthedocs.org/projects/anymail/badge/?version=stable :target: https://anymail.readthedocs.io/en/stable/ diff --git a/docs/contributing.rst b/docs/contributing.rst index 11c1b95..e8eb08b 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -66,7 +66,7 @@ Pull requests are always welcome to fix bugs and improve support for ESP and Dja Testing ------- -Anymail is `tested on Travis CI`_ against several combinations of Django +Anymail is `tested via GitHub Actions`_ against several combinations of Django and Python versions. Tests are run at least once a week, to check whether ESP APIs and other dependencies have changed out from under Anymail. @@ -119,8 +119,8 @@ API keys or other settings. For example: .. code-block:: console - $ export MAILGUN_TEST_API_KEY='your-Mailgun-API-key' - $ export MAILGUN_TEST_DOMAIN='mail.example.com' # sending domain for that API key + $ export ANYMAIL_TEST_MAILGUN_API_KEY='your-Mailgun-API-key' + $ export ANYMAIL_TEST_MAILGUN_DOMAIN='mail.example.com' # sending domain for that API key $ tox -e django31-py38-all tests.test_mailgun_integration Check the ``*_integration_tests.py`` files in the `tests source`_ to see which variables @@ -132,7 +132,7 @@ for all 20+ supported combinations of Python and Django, sending hundreds of mes .. _pyenv: https://github.com/pyenv/pyenv -.. _tested on Travis CI: https://travis-ci.org/anymail/django-anymail +.. _tested via GitHub Actions: https://github.com/anymail/django-anymail/actions?query=workflow:test .. _tests source: https://github.com/anymail/django-anymail/blob/main/tests .. _.travis.yml: https://github.com/anymail/django-anymail/blob/main/.travis.yml diff --git a/runtests.py b/runtests.py index c29ab98..1d6a273 100755 --- a/runtests.py +++ b/runtests.py @@ -22,7 +22,7 @@ def setup_and_run_tests(test_labels=None): exclude_tags = envlist('ANYMAIL_SKIP_TESTS') # In automated testing, don't run live tests unless specifically requested - if envbool('CONTINUOUS_INTEGRATION') and not envbool('RUN_LIVE_TESTS'): + if envbool('CONTINUOUS_INTEGRATION') and not envbool('ANYMAIL_RUN_LIVE_TESTS'): exclude_tags.append('live') if tags: @@ -49,13 +49,13 @@ def runtests(test_labels=None): def envbool(var, default=False): - """Returns value of environment variable var as a bool, or default if not set. + """Returns value of environment variable var as a bool, or default if not set/empty. Converts `'true'` to `True`, and `'false'` to `False`. See :func:`~distutils.util.strtobool` for full list of allowable values. """ - val = os.getenv(var, None) - if val is None: + val = os.getenv(var, '') + if val == '': return default else: return strtobool(val) diff --git a/setup.py b/setup.py index bbe3a33..59497db 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ with open(path.join(here, "anymail/_version.py"), encoding='utf-8') as f: def long_description_from_readme(rst): # Freeze external links (on PyPI) to refer to this X.Y or X.Y.Z tag. # (This relies on tagging releases with 'vX.Y' or 'vX.Y.Z' in GitHub.) - rst = re.sub(r'(?<=branch=)main' # Travis build status: branch=main --> branch=vX.Y.Z + rst = re.sub(r'(?<=branch[=:])main' # GitHub Actions build status: branch=main --> branch=vX.Y.Z r'|(?<=/)stable' # ReadTheDocs links: /stable --> /vX.Y.Z r'|(?<=version=)stable', # ReadTheDocs badge: version=stable --> version=vX.Y.Z release_tag, rst) # (?<=...) is "positive lookbehind": must be there, but won't get replaced diff --git a/tests/test_amazon_ses_integration.py b/tests/test_amazon_ses_integration.py index 8a20d16..c895d0d 100644 --- a/tests/test_amazon_ses_integration.py +++ b/tests/test_amazon_ses_integration.py @@ -10,13 +10,13 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin, sample_image_path -AMAZON_SES_TEST_ACCESS_KEY_ID = os.getenv("AMAZON_SES_TEST_ACCESS_KEY_ID") -AMAZON_SES_TEST_SECRET_ACCESS_KEY = os.getenv("AMAZON_SES_TEST_SECRET_ACCESS_KEY") -AMAZON_SES_TEST_REGION_NAME = os.getenv("AMAZON_SES_TEST_REGION_NAME", "us-east-1") +ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID = os.getenv("ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID") +ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY = os.getenv("ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY") +ANYMAIL_TEST_AMAZON_SES_REGION_NAME = os.getenv("ANYMAIL_TEST_AMAZON_SES_REGION_NAME", "us-east-1") -@unittest.skipUnless(AMAZON_SES_TEST_ACCESS_KEY_ID and AMAZON_SES_TEST_SECRET_ACCESS_KEY, - "Set AMAZON_SES_TEST_ACCESS_KEY_ID and AMAZON_SES_TEST_SECRET_ACCESS_KEY " +@unittest.skipUnless(ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID and ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY, + "Set ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID and ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY " "environment variables to run Amazon SES integration tests") @override_settings( EMAIL_BACKEND="anymail.backends.amazon_ses.EmailBackend", @@ -25,9 +25,9 @@ AMAZON_SES_TEST_REGION_NAME = os.getenv("AMAZON_SES_TEST_REGION_NAME", "us-east- # This setting provides Anymail-specific AWS credentials to boto3.client(), # overriding any credentials in the environment or boto config. It's often # *not* the best approach -- see the Anymail and boto3 docs for other options. - "aws_access_key_id": AMAZON_SES_TEST_ACCESS_KEY_ID, - "aws_secret_access_key": AMAZON_SES_TEST_SECRET_ACCESS_KEY, - "region_name": AMAZON_SES_TEST_REGION_NAME, + "aws_access_key_id": ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID, + "aws_secret_access_key": ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY, + "region_name": ANYMAIL_TEST_AMAZON_SES_REGION_NAME, # Can supply any other boto3.client params, including botocore.config.Config as dict "config": {"retries": {"max_attempts": 2}}, }, @@ -38,9 +38,9 @@ class AmazonSESBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): """Amazon SES API integration tests These tests run against the **live** Amazon SES API, using the environment - variables `AMAZON_SES_TEST_ACCESS_KEY_ID` and `AMAZON_SES_TEST_SECRET_ACCESS_KEY` + variables `ANYMAIL_TEST_AMAZON_SES_ACCESS_KEY_ID` and `ANYMAIL_TEST_AMAZON_SES_SECRET_ACCESS_KEY` as AWS credentials. If those variables are not set, these tests won't run. - (You can also set the environment variable `AMAZON_SES_TEST_REGION_NAME` + (You can also set the environment variable `ANYMAIL_TEST_AMAZON_SES_REGION_NAME` to test SES using a region other than the default "us-east-1".) Amazon SES doesn't offer a test mode -- it tries to send everything you ask. @@ -142,7 +142,7 @@ class AmazonSESBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): "AMAZON_SES_CLIENT_PARAMS": { "aws_access_key_id": "test-invalid-access-key-id", "aws_secret_access_key": "test-invalid-secret-access-key", - "region_name": AMAZON_SES_TEST_REGION_NAME, + "region_name": ANYMAIL_TEST_AMAZON_SES_REGION_NAME, } }) def test_invalid_aws_credentials(self): diff --git a/tests/test_mailgun_integration.py b/tests/test_mailgun_integration.py index 0df0c06..6e0aa20 100644 --- a/tests/test_mailgun_integration.py +++ b/tests/test_mailgun_integration.py @@ -12,24 +12,24 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin, sample_image_path -MAILGUN_TEST_API_KEY = os.getenv('MAILGUN_TEST_API_KEY') -MAILGUN_TEST_DOMAIN = os.getenv('MAILGUN_TEST_DOMAIN') +ANYMAIL_TEST_MAILGUN_API_KEY = os.getenv('ANYMAIL_TEST_MAILGUN_API_KEY') +ANYMAIL_TEST_MAILGUN_DOMAIN = os.getenv('ANYMAIL_TEST_MAILGUN_DOMAIN') @tag('mailgun', 'live') -@unittest.skipUnless(MAILGUN_TEST_API_KEY and MAILGUN_TEST_DOMAIN, - "Set MAILGUN_TEST_API_KEY and MAILGUN_TEST_DOMAIN environment variables " +@unittest.skipUnless(ANYMAIL_TEST_MAILGUN_API_KEY and ANYMAIL_TEST_MAILGUN_DOMAIN, + "Set ANYMAIL_TEST_MAILGUN_API_KEY and ANYMAIL_TEST_MAILGUN_DOMAIN environment variables " "to run Mailgun integration tests") -@override_settings(ANYMAIL={'MAILGUN_API_KEY': MAILGUN_TEST_API_KEY, - 'MAILGUN_SENDER_DOMAIN': MAILGUN_TEST_DOMAIN, +@override_settings(ANYMAIL={'MAILGUN_API_KEY': ANYMAIL_TEST_MAILGUN_API_KEY, + 'MAILGUN_SENDER_DOMAIN': ANYMAIL_TEST_MAILGUN_DOMAIN, 'MAILGUN_SEND_DEFAULTS': {'esp_extra': {'o:testmode': 'yes'}}}, EMAIL_BACKEND="anymail.backends.mailgun.EmailBackend") class MailgunBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): """Mailgun API integration tests These tests run against the **live** Mailgun API, using the - environment variable `MAILGUN_TEST_API_KEY` as the API key - and `MAILGUN_TEST_DOMAIN` as the sender domain. + environment variable `ANYMAIL_TEST_MAILGUN_API_KEY` as the API key + and `ANYMAIL_TEST_MAILGUN_DOMAIN` as the sender domain. If those variables are not set, these tests won't run. """ @@ -43,8 +43,8 @@ class MailgunBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): def fetch_mailgun_events(self, message_id, event=None, initial_delay=2, retry_delay=2, max_retries=5): """Return list of Mailgun events related to message_id""" - url = "https://api.mailgun.net/v3/%s/events" % MAILGUN_TEST_DOMAIN - auth = ("api", MAILGUN_TEST_API_KEY) + url = "https://api.mailgun.net/v3/%s/events" % ANYMAIL_TEST_MAILGUN_DOMAIN + auth = ("api", ANYMAIL_TEST_MAILGUN_API_KEY) # Despite the docs, Mailgun's events API actually expects the message-id # without the <...> brackets (so, not exactly "as returned by the messages API") @@ -116,7 +116,7 @@ class MailgunBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): ) message.attach("attachment1.txt", "Here is some\ntext for you", "text/plain") message.attach("vedhæftet fil.csv", "ID,Name\n1,3", "text/csv") - cid = message.attach_inline_image_file(sample_image_path(), domain=MAILGUN_TEST_DOMAIN) + cid = message.attach_inline_image_file(sample_image_path(), domain=ANYMAIL_TEST_MAILGUN_DOMAIN) message.attach_alternative( "
This is the html body
" % cid, "text/html") @@ -195,7 +195,7 @@ class MailgunBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): # self.assertIn("'from' parameter is not a valid address", str(err)) @override_settings(ANYMAIL={'MAILGUN_API_KEY': "Hey, that's not an API key", - 'MAILGUN_SENDER_DOMAIN': MAILGUN_TEST_DOMAIN, + 'MAILGUN_SENDER_DOMAIN': ANYMAIL_TEST_MAILGUN_DOMAIN, 'MAILGUN_SEND_DEFAULTS': {'esp_extra': {'o:testmode': 'yes'}}}) def test_invalid_api_key(self): with self.assertRaises(AnymailAPIError) as cm: diff --git a/tests/test_mailjet_integration.py b/tests/test_mailjet_integration.py index b55f900..f9e2707 100644 --- a/tests/test_mailjet_integration.py +++ b/tests/test_mailjet_integration.py @@ -8,16 +8,16 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin, sample_image_path -MAILJET_TEST_API_KEY = os.getenv('MAILJET_TEST_API_KEY') -MAILJET_TEST_SECRET_KEY = os.getenv('MAILJET_TEST_SECRET_KEY') +ANYMAIL_TEST_MAILJET_API_KEY = os.getenv('ANYMAIL_TEST_MAILJET_API_KEY') +ANYMAIL_TEST_MAILJET_SECRET_KEY = os.getenv('ANYMAIL_TEST_MAILJET_SECRET_KEY') @tag('mailjet', 'live') -@unittest.skipUnless(MAILJET_TEST_API_KEY and MAILJET_TEST_SECRET_KEY, - "Set MAILJET_TEST_API_KEY and MAILJET_TEST_SECRET_KEY " +@unittest.skipUnless(ANYMAIL_TEST_MAILJET_API_KEY and ANYMAIL_TEST_MAILJET_SECRET_KEY, + "Set ANYMAIL_TEST_MAILJET_API_KEY and ANYMAIL_TEST_MAILJET_SECRET_KEY " "environment variables to run Mailjet integration tests") -@override_settings(ANYMAIL={"MAILJET_API_KEY": MAILJET_TEST_API_KEY, - "MAILJET_SECRET_KEY": MAILJET_TEST_SECRET_KEY, +@override_settings(ANYMAIL={"MAILJET_API_KEY": ANYMAIL_TEST_MAILJET_API_KEY, + "MAILJET_SECRET_KEY": ANYMAIL_TEST_MAILJET_SECRET_KEY, "MAILJET_SEND_DEFAULTS": {"esp_extra": {"SandboxMode": True}}, # don't actually send mail }, EMAIL_BACKEND="anymail.backends.mailjet.EmailBackend") @@ -25,7 +25,7 @@ class MailjetBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): """Mailjet API integration tests These tests run against the **live** Mailjet API, using the - environment variables `MAILJET_TEST_API_KEY` and `MAILJET_TEST_SECRET_KEY` + environment variables `ANYMAIL_TEST_MAILJET_API_KEY` and `ANYMAIL_TEST_MAILJET_SECRET_KEY` as the API key and API secret key, respectively. If those variables are not set, these tests won't run. diff --git a/tests/test_mandrill_integration.py b/tests/test_mandrill_integration.py index 27aef00..e92779a 100644 --- a/tests/test_mandrill_integration.py +++ b/tests/test_mandrill_integration.py @@ -9,19 +9,19 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin, sample_image_path -MANDRILL_TEST_API_KEY = os.getenv('MANDRILL_TEST_API_KEY') +ANYMAIL_TEST_MANDRILL_API_KEY = os.getenv('ANYMAIL_TEST_MANDRILL_API_KEY') @tag('mandrill', 'live') -@unittest.skipUnless(MANDRILL_TEST_API_KEY, - "Set MANDRILL_TEST_API_KEY environment variable to run integration tests") -@override_settings(MANDRILL_API_KEY=MANDRILL_TEST_API_KEY, +@unittest.skipUnless(ANYMAIL_TEST_MANDRILL_API_KEY, + "Set ANYMAIL_TEST_MANDRILL_API_KEY environment variable to run integration tests") +@override_settings(MANDRILL_API_KEY=ANYMAIL_TEST_MANDRILL_API_KEY, EMAIL_BACKEND="anymail.backends.mandrill.EmailBackend") class MandrillBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): """Mandrill API integration tests These tests run against the **live** Mandrill API, using the - environment variable `MANDRILL_TEST_API_KEY` as the API key. + environment variable `ANYMAIL_TEST_MANDRILL_API_KEY` as the API key. If that variable is not set, these tests won't run. See https://mandrill.zendesk.com/hc/en-us/articles/205582447 diff --git a/tests/test_postmark_integration.py b/tests/test_postmark_integration.py index 4494423..c4822a4 100644 --- a/tests/test_postmark_integration.py +++ b/tests/test_postmark_integration.py @@ -11,8 +11,8 @@ from .utils import AnymailTestMixin, sample_image_path # For most integration tests, Postmark's sandboxed "POSTMARK_API_TEST" token is used. # But to test template sends, a real Postmark server token and template id are needed: -POSTMARK_TEST_SERVER_TOKEN = os.getenv('POSTMARK_TEST_SERVER_TOKEN') -POSTMARK_TEST_TEMPLATE_ID = os.getenv('POSTMARK_TEST_TEMPLATE_ID') +ANYMAIL_TEST_POSTMARK_SERVER_TOKEN = os.getenv('ANYMAIL_TEST_POSTMARK_SERVER_TOKEN') +ANYMAIL_TEST_POSTMARK_TEMPLATE_ID = os.getenv('ANYMAIL_TEST_POSTMARK_TEMPLATE_ID') @tag('postmark', 'live') @@ -88,15 +88,15 @@ class PostmarkBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): self.assertEqual(err.status_code, 422) self.assertIn("Invalid 'From' address", str(err)) - @unittest.skipUnless(POSTMARK_TEST_SERVER_TOKEN and POSTMARK_TEST_TEMPLATE_ID, - "Set POSTMARK_TEST_SERVER_TOKEN and POSTMARK_TEST_TEMPLATE_ID " + @unittest.skipUnless(ANYMAIL_TEST_POSTMARK_SERVER_TOKEN and ANYMAIL_TEST_POSTMARK_TEMPLATE_ID, + "Set ANYMAIL_TEST_POSTMARK_SERVER_TOKEN and ANYMAIL_TEST_POSTMARK_TEMPLATE_ID " "environment variables to run Postmark template integration tests") - @override_settings(ANYMAIL_POSTMARK_SERVER_TOKEN=POSTMARK_TEST_SERVER_TOKEN) + @override_settings(ANYMAIL_POSTMARK_SERVER_TOKEN=ANYMAIL_TEST_POSTMARK_SERVER_TOKEN) def test_template(self): message = AnymailMessage( from_email="from@test-pm.anymail.info", to=["test+to1@anymail.info", "Second Recipient "], - template_id=POSTMARK_TEST_TEMPLATE_ID, + template_id=ANYMAIL_TEST_POSTMARK_TEMPLATE_ID, merge_data={ "test+to1@anymail.info": {"name": "Recipient 1", "order_no": "12345"}, "test+to2@anymail.info": {"order_no": "6789"}, diff --git a/tests/test_sendgrid_integration.py b/tests/test_sendgrid_integration.py index c6434fe..5c5b6f7 100644 --- a/tests/test_sendgrid_integration.py +++ b/tests/test_sendgrid_integration.py @@ -9,15 +9,15 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin, sample_image_path -SENDGRID_TEST_API_KEY = os.getenv('SENDGRID_TEST_API_KEY') -SENDGRID_TEST_TEMPLATE_ID = os.getenv('SENDGRID_TEST_TEMPLATE_ID') +ANYMAIL_TEST_SENDGRID_API_KEY = os.getenv('ANYMAIL_TEST_SENDGRID_API_KEY') +ANYMAIL_TEST_SENDGRID_TEMPLATE_ID = os.getenv('ANYMAIL_TEST_SENDGRID_TEMPLATE_ID') @tag('sendgrid', 'live') -@unittest.skipUnless(SENDGRID_TEST_API_KEY, - "Set SENDGRID_TEST_API_KEY environment variable " +@unittest.skipUnless(ANYMAIL_TEST_SENDGRID_API_KEY, + "Set ANYMAIL_TEST_SENDGRID_API_KEY environment variable " "to run SendGrid integration tests") -@override_settings(ANYMAIL_SENDGRID_API_KEY=SENDGRID_TEST_API_KEY, +@override_settings(ANYMAIL_SENDGRID_API_KEY=ANYMAIL_TEST_SENDGRID_API_KEY, ANYMAIL_SENDGRID_SEND_DEFAULTS={"esp_extra": { "mail_settings": {"sandbox_mode": {"enable": True}}, }}, @@ -26,7 +26,7 @@ class SendGridBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): """SendGrid v3 API integration tests These tests run against the **live** SendGrid API, using the - environment variable `SENDGRID_TEST_API_KEY` as the API key + environment variable `ANYMAIL_TEST_SENDGRID_API_KEY` as the API key If those variables are not set, these tests won't run. The SEND_DEFAULTS above force SendGrid's v3 sandbox mode, which avoids sending mail. @@ -107,15 +107,15 @@ class SendGridBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): self.assertEqual(recipient_status['to1@sink.sendgrid.net'].status, 'queued') self.assertEqual(recipient_status['to2@sink.sendgrid.net'].status, 'queued') - @unittest.skipUnless(SENDGRID_TEST_TEMPLATE_ID, - "Set the SENDGRID_TEST_TEMPLATE_ID environment variable " + @unittest.skipUnless(ANYMAIL_TEST_SENDGRID_TEMPLATE_ID, + "Set the ANYMAIL_TEST_SENDGRID_TEMPLATE_ID environment variable " "to a template in your SendGrid account to test stored templates") def test_stored_template(self): message = AnymailMessage( from_email="Test From ", to=["to@sink.sendgrid.net"], # Anymail's live test template has merge fields "name", "order_no", and "dept"... - template_id=SENDGRID_TEST_TEMPLATE_ID, + template_id=ANYMAIL_TEST_SENDGRID_TEMPLATE_ID, merge_data={ 'to@sink.sendgrid.net': { 'name': "Test Recipient", diff --git a/tests/test_sendinblue_integration.py b/tests/test_sendinblue_integration.py index 50e6641..0c0ca0a 100644 --- a/tests/test_sendinblue_integration.py +++ b/tests/test_sendinblue_integration.py @@ -8,14 +8,14 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin -SENDINBLUE_TEST_API_KEY = os.getenv('SENDINBLUE_TEST_API_KEY') +ANYMAIL_TEST_SENDINBLUE_API_KEY = os.getenv('ANYMAIL_TEST_SENDINBLUE_API_KEY') @tag('sendinblue', 'live') -@unittest.skipUnless(SENDINBLUE_TEST_API_KEY, - "Set SENDINBLUE_TEST_API_KEY environment variable " +@unittest.skipUnless(ANYMAIL_TEST_SENDINBLUE_API_KEY, + "Set ANYMAIL_TEST_SENDINBLUE_API_KEY environment variable " "to run SendinBlue integration tests") -@override_settings(ANYMAIL_SENDINBLUE_API_KEY=SENDINBLUE_TEST_API_KEY, +@override_settings(ANYMAIL_SENDINBLUE_API_KEY=ANYMAIL_TEST_SENDINBLUE_API_KEY, ANYMAIL_SENDINBLUE_SEND_DEFAULTS=dict(), EMAIL_BACKEND="anymail.backends.sendinblue.EmailBackend") class SendinBlueBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): @@ -23,7 +23,7 @@ class SendinBlueBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): SendinBlue doesn't have sandbox so these tests run against the **live** SendinBlue API, using the - environment variable `SENDINBLUE_TEST_API_KEY` as the API key + environment variable `ANYMAIL_TEST_SENDINBLUE_API_KEY` as the API key If those variables are not set, these tests won't run. https://developers.sendinblue.com/docs/faq#section-how-can-i-test-the-api- diff --git a/tests/test_sparkpost_integration.py b/tests/test_sparkpost_integration.py index 013c936..e87ef1d 100644 --- a/tests/test_sparkpost_integration.py +++ b/tests/test_sparkpost_integration.py @@ -9,20 +9,20 @@ from anymail.message import AnymailMessage from .utils import AnymailTestMixin, sample_image_path -SPARKPOST_TEST_API_KEY = os.getenv('SPARKPOST_TEST_API_KEY') +ANYMAIL_TEST_SPARKPOST_API_KEY = os.getenv('ANYMAIL_TEST_SPARKPOST_API_KEY') @tag('sparkpost', 'live') -@unittest.skipUnless(SPARKPOST_TEST_API_KEY, - "Set SPARKPOST_TEST_API_KEY environment variable " +@unittest.skipUnless(ANYMAIL_TEST_SPARKPOST_API_KEY, + "Set ANYMAIL_TEST_SPARKPOST_API_KEY environment variable " "to run SparkPost integration tests") -@override_settings(ANYMAIL_SPARKPOST_API_KEY=SPARKPOST_TEST_API_KEY, +@override_settings(ANYMAIL_SPARKPOST_API_KEY=ANYMAIL_TEST_SPARKPOST_API_KEY, EMAIL_BACKEND="anymail.backends.sparkpost.EmailBackend") class SparkPostBackendIntegrationTests(AnymailTestMixin, SimpleTestCase): """SparkPost API integration tests These tests run against the **live** SparkPost API, using the - environment variable `SPARKPOST_TEST_API_KEY` as the API key + environment variable `ANYMAIL_TEST_SPARKPOST_API_KEY` as the API key If that variable is not set, these tests won't run. SparkPost doesn't offer a test mode -- it tries to send everything diff --git a/tox.ini b/tox.ini index bb41cde..ed84e55 100644 --- a/tox.ini +++ b/tox.ini @@ -47,16 +47,9 @@ commands = passenv = ANYMAIL_ONLY_TEST ANYMAIL_SKIP_TESTS - RUN_LIVE_TESTS + ANYMAIL_RUN_LIVE_TESTS CONTINUOUS_INTEGRATION - AMAZON_SES_TEST_* - MAILGUN_TEST_* - MAILJET_TEST_* - MANDRILL_TEST_* - POSTMARK_TEST_* - SENDINBLUE_TEST_* - SENDGRID_TEST_* - SPARKPOST_TEST_* + ANYMAIL_TEST_* [testenv:lint] basepython = python3