Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Automated Testing: Philosophy & Tools

Automated Testing: Philosophy & Tools

A rundown of the benefits of automated testing and how to practically do it with tox and travis.

Stephen Burrows

June 25, 2013
Tweet

Other Decks in Programming

Transcript

  1. I won’t cover • Jenkins • pip and virtualenv •

    deployment • python 3 compatibility
  2. The ideal • Test with every supported python version •

    Test with every database/search backend • Test with every supported dependency version • Test every possible combination
  3. Without automation ~Test with every supported python version ⨉Test with

    every database/search backend ~Test with every supported dependency version ⨉Test every possible combination
  4. With automation ✓Test with every supported python version ~Test with

    every database/search backend ~Test with every supported dependency version ~Test every possible combination
  5. Package layout django-daguerre/ .travis.yml AUTHORS LICENSE MANIFEST.in setup.py tox.ini daguerre/

    docs/ test_project/ requirements-1.4.txt requirements-1.5.txt manage.py test_project/
  6. Test project django-daguerre/ .travis.yml AUTHORS LICENSE MANIFEST.in setup.py tox.ini daguerre/

    docs/ test_project/ requirements-1.4.txt requirements-1.5.txt manage.py test_project/
  7. Requirements files django-daguerre/ .travis.yml AUTHORS LICENSE MANIFEST.in setup.py tox.ini daguerre/

    docs/ test_project/ requirements-1.4.txt requirements-1.5.txt manage.py test_project/
  8. ⨉ No django-nose south mock six Pillow Pillow>2.0.0 django<1.5 -e

    git+https://github.com/jbalogh/django-nose.git@ master#egg=django-nose south>0.8 mock six
  9. tox: local testing django-daguerre/ .travis.yml AUTHORS LICENSE MANIFEST.in setup.py tox.ini

    daguerre/ docs/ test_project/ requirements-1.4.txt requirements-1.5.txt manage.py test_project/
  10. • Isolated virtual environments • Multiple versions of python •

    Local == pre-commit • .../django-daguerre$ tox
  11. tox.ini (basic) [tox] envlist = py26, py27, py33 [testenv] changedir

    = {toxinidir}/test_project deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.4.txt commands = {envpython} manage.py test daguerre
  12. tox.ini (matrix) [tox] envlist = py26-django14, py27-django14, py26-django15, py27-django15, [testenv]

    changedir = {toxinidir}/test_project commands = {envpython} manage.py test daguerre # Continued
  13. tox.ini (matrix) [testenv:py26-django14] basepython=python2.6 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.4.txt [testenv:py27-django14]

    basepython=python2.7 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.4.txt [testenv:py26-django15] basepython=python2.6 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.5.txt [testenv:py27-django15] basepython=python2.7 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.5.txt
  14. travis-ci: remote testing django-daguerre/ .travis.yml AUTHORS LICENSE MANIFEST.in setup.py tox.ini

    daguerre/ docs/ test_project/ requirements-1.4.txt requirements-1.5.txt manage.py test_project/
  15. • Isolated virtual environments • Multiple versions of python •

    Good matrix support • Built-in support for MySQL, PostgreSQL, Elasticsearch, Redis, and more • Remote == post-push • Integration for public Github repos only
  16. .travis.yml (basic) language: python python: - "2.6" - "2.7" -

    "3.3" install: - pip install . --no-deps - pip install --use-mirrors --no-deps -r test_project/requirements-1.5.txt script: - cd test_project - ./manage.py test --verbosity=2 daguerre
  17. tox.ini (basic) [tox] envlist = py26, py27, py33 [testenv] changedir

    = {toxinidir}/test_project deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.4.txt commands = {envpython} manage.py test daguerre
  18. .travis.yml (matrix) language: python python: - "2.6" - "2.7" -

    "3.3" env: - REQUIREMENTS=test_project/requirements-1.4.txt - REQUIREMENTS=test_project/requirements-1.5.txt matrix: exclude: - python: "3.3" env: REQUIREMENTS=test_project/requirements-1.4.txt install: - pip install . --no-deps - pip install --use-mirrors --no-deps -r $REQUIREMENTS script: - cd test_project - ./manage.py test --verbosity=2 daguerre
  19. tox.ini (matrix) [tox] envlist = py26-django14, py27-django14, py26-django15, py27-django15, [testenv]

    changedir = {toxinidir}/test_project commands = {envpython} manage.py test daguerre # Continued
  20. tox.ini (matrix) [testenv:py26-django14] basepython=python2.6 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.4.txt [testenv:py27-django14]

    basepython=python2.7 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.4.txt [testenv:py26-django15] basepython=python2.6 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.5.txt [testenv:py27-django15] basepython=python2.7 deps = --no-deps --use-mirrors -r{toxinidir}/test_project/requirements-1.5.txt
  21. .travis.yml (matrix 2) language: python python: - "2.6" - "2.7"

    - "3.3" env: - DB=sqlite3 REQUIREMENTS=test_project/requirements-1.4.txt - DB=mysql REQUIREMENTS=test_project/requirements-1.4.txt - DB=sqlite3 REQUIREMENTS=test_project/requirements-1.5.txt - DB=mysql REQUIREMENTS=test_project/requirements-1.5.txt matrix: exclude: - python: "3.3" env: DB=sqlite3 REQUIREMENTS=test_project/requirements-1.4.txt - python: "3.3" env: DB=mysql REQUIREMENTS=test_project/requirements-1.4.txt - python: "3.3" env: DB=mysql REQUIREMENTS=test_project/requirements-1.5.txt install: - pip install . --no-deps - pip install --use-mirrors --no-deps -r $REQUIREMENTS - if [ $DB == 'mysql' ]; then pip install --use-mirrors --no-deps mysql-python; fi before_script: - if [ $DB == 'mysql' ]; then mysql -e 'CREATE DATABASE daguerre_test;'; fi script: - cd test_project - ./manage.py test --verbosity=2 daguerre
  22. (in settings.py) import os DB = os.environ.get('DB') if DB ==

    'mysql': DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'daguerre_test', 'USER': 'root', 'TEST_CHARSET': 'utf8', 'TEST_COLLATION': 'utf8_general_ci', } } else: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(PROJECT_DIR, 'db.sl3'), } }
  23. Summary (tox) • Multiple versions of python: trivial • Two-dimensional

    matrix: work, but possible • For example, multiple versions of django • Higher-dimensional matrix: not really feasible • For example multiple versions of django and multiple database settings
  24. Summary (travis) • Multiple versions of python: trivial • Two-dimensional

    matrix: simple • For example, multiple versions of django • Higher-dimensional matrix: work, but possible • For example multiple versions of django and multiple database settings