From 077d06df5498d51c98983562cff876aff4ab862b Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 31 Aug 2014 21:48:05 +0200 Subject: [PATCH 01/33] Remove run-simple.py --- run-tests.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 run-tests.py diff --git a/run-tests.py b/run-tests.py deleted file mode 100644 index c1345848..00000000 --- a/run-tests.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -import sys, os -sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) -from flask.testsuite import main -main() From 3550b26071e0f392ad67ece2ea5057a292bdc528 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 31 Aug 2014 21:48:21 +0200 Subject: [PATCH 02/33] Move tests --- MANIFEST.in | 5 +---- .../lib/python2.5/site-packages/SiteEgg.egg | Bin 1218 -> 0 bytes setup.py | 3 +-- {flask/testsuite => tests}/__init__.py | 0 {flask/testsuite => tests}/appctx.py | 0 {flask/testsuite => tests}/basic.py | 0 {flask/testsuite => tests}/blueprints.py | 0 {flask/testsuite => tests}/config.py | 0 {flask/testsuite => tests}/deprecations.py | 0 {flask/testsuite => tests}/examples.py | 0 {flask/testsuite => tests}/ext.py | 0 {flask/testsuite => tests}/helpers.py | 0 {flask/testsuite => tests}/regression.py | 0 {flask/testsuite => tests}/reqctx.py | 0 {flask/testsuite => tests}/signals.py | 0 {flask/testsuite => tests}/static/config.json | 0 {flask/testsuite => tests}/static/index.html | 0 {flask/testsuite => tests}/subclassing.py | 0 {flask/testsuite => tests}/templates/_macro.html | 0 .../templates/context_template.html | 0 .../templates/escaping_template.html | 0 {flask/testsuite => tests}/templates/mail.txt | 0 .../templates/nested/nested.txt | 0 .../templates/simple_template.html | 0 .../templates/template_filter.html | 0 .../templates/template_test.html | 0 {flask/testsuite => tests}/templating.py | 0 .../test_apps/blueprintapp/__init__.py | 0 .../test_apps/blueprintapp/apps/__init__.py | 0 .../blueprintapp/apps/admin/__init__.py | 0 .../blueprintapp/apps/admin/static/css/test.css | 0 .../blueprintapp/apps/admin/static/test.txt | 0 .../apps/admin/templates/admin/index.html | 0 .../blueprintapp/apps/frontend/__init__.py | 0 .../apps/frontend/templates/frontend/index.html | 0 .../test_apps/config_module_app.py | 0 .../test_apps/config_package_app/__init__.py | 0 .../test_apps/flask_broken/__init__.py | 0 .../test_apps/flask_broken/b.py | 0 .../test_apps/flask_newext_package/__init__.py | 0 .../test_apps/flask_newext_package/submodule.py | 0 .../test_apps/flask_newext_simple.py | 0 .../test_apps/flaskext/__init__.py | 0 .../flaskext/oldext_package/__init__.py | 0 .../flaskext/oldext_package/submodule.py | 0 .../test_apps/flaskext/oldext_simple.py | 0 .../testsuite => tests}/test_apps/importerror.py | 0 .../lib/python2.5/site-packages/site_app.py | 0 .../site-packages/site_package/__init__.py | 0 {flask/testsuite => tests}/test_apps/main_app.py | 0 .../test_apps/path/installed_package/__init__.py | 0 .../test_apps/subdomaintestmodule/__init__.py | 0 .../subdomaintestmodule/static/hello.txt | 0 {flask/testsuite => tests}/testing.py | 0 {flask/testsuite => tests}/views.py | 0 55 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 flask/testsuite/test_apps/lib/python2.5/site-packages/SiteEgg.egg rename {flask/testsuite => tests}/__init__.py (100%) rename {flask/testsuite => tests}/appctx.py (100%) rename {flask/testsuite => tests}/basic.py (100%) rename {flask/testsuite => tests}/blueprints.py (100%) rename {flask/testsuite => tests}/config.py (100%) rename {flask/testsuite => tests}/deprecations.py (100%) rename {flask/testsuite => tests}/examples.py (100%) rename {flask/testsuite => tests}/ext.py (100%) rename {flask/testsuite => tests}/helpers.py (100%) rename {flask/testsuite => tests}/regression.py (100%) rename {flask/testsuite => tests}/reqctx.py (100%) rename {flask/testsuite => tests}/signals.py (100%) rename {flask/testsuite => tests}/static/config.json (100%) rename {flask/testsuite => tests}/static/index.html (100%) rename {flask/testsuite => tests}/subclassing.py (100%) rename {flask/testsuite => tests}/templates/_macro.html (100%) rename {flask/testsuite => tests}/templates/context_template.html (100%) rename {flask/testsuite => tests}/templates/escaping_template.html (100%) rename {flask/testsuite => tests}/templates/mail.txt (100%) rename {flask/testsuite => tests}/templates/nested/nested.txt (100%) rename {flask/testsuite => tests}/templates/simple_template.html (100%) rename {flask/testsuite => tests}/templates/template_filter.html (100%) rename {flask/testsuite => tests}/templates/template_test.html (100%) rename {flask/testsuite => tests}/templating.py (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/admin/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/admin/static/css/test.css (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/admin/static/test.txt (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/admin/templates/admin/index.html (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/frontend/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html (100%) rename {flask/testsuite => tests}/test_apps/config_module_app.py (100%) rename {flask/testsuite => tests}/test_apps/config_package_app/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/flask_broken/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/flask_broken/b.py (100%) rename {flask/testsuite => tests}/test_apps/flask_newext_package/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/flask_newext_package/submodule.py (100%) rename {flask/testsuite => tests}/test_apps/flask_newext_simple.py (100%) rename {flask/testsuite => tests}/test_apps/flaskext/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/flaskext/oldext_package/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/flaskext/oldext_package/submodule.py (100%) rename {flask/testsuite => tests}/test_apps/flaskext/oldext_simple.py (100%) rename {flask/testsuite => tests}/test_apps/importerror.py (100%) rename {flask/testsuite => tests}/test_apps/lib/python2.5/site-packages/site_app.py (100%) rename {flask/testsuite => tests}/test_apps/lib/python2.5/site-packages/site_package/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/main_app.py (100%) rename {flask/testsuite => tests}/test_apps/path/installed_package/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/subdomaintestmodule/__init__.py (100%) rename {flask/testsuite => tests}/test_apps/subdomaintestmodule/static/hello.txt (100%) rename {flask/testsuite => tests}/testing.py (100%) rename {flask/testsuite => tests}/views.py (100%) diff --git a/MANIFEST.in b/MANIFEST.in index f82ed054..3fef8b5b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ -include Makefile CHANGES LICENSE AUTHORS run-tests.py +include Makefile CHANGES LICENSE AUTHORS recursive-include artwork * recursive-include tests * recursive-include examples * @@ -9,8 +9,5 @@ recursive-exclude tests *.pyc recursive-exclude tests *.pyo recursive-exclude examples *.pyc recursive-exclude examples *.pyo -recursive-include flask/testsuite/static * -recursive-include flask/testsuite/templates * -recursive-include flask/testsuite/test_apps * prune docs/_build prune docs/_themes/.git diff --git a/flask/testsuite/test_apps/lib/python2.5/site-packages/SiteEgg.egg b/flask/testsuite/test_apps/lib/python2.5/site-packages/SiteEgg.egg deleted file mode 100644 index d80abe9309fb1a9d0c4fce1fd76e87679282a012..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1218 zcmWIWW@Zs#U|`^2*i@|Uz;wUq#B3n%6cFX;jJGoR?{Kkt3Ux3^zEk*!FGo6E$(OtB+LU}ngynUfdIpE4;jX3_M? zGsB}6MkgkU<)*?p_uOI9m8szL6tXEP|qV1=vse3_t#S^V_I-b4$ zzW(eRn;Ub&6@*V*J$uIc^mYCZW!JxcDgJzX3gm$)b%*)?RnOF zUC;TGXHM%KTenJOzk;3mRvlAz6<#!VOlG@o#0<2b5r}1x-I0=7keZj0nwMM|pOcxF zT?}&2V48(%Sx&yo+-udjS>*?dE<9UVGTUYDcne&^246YbI_ymlm ztw9_>UzPg$KX;nQrFZtMugTxS3sC#m^5x3WYvV$zlMMB<}K6MufDxtZLf6euYpt#}$Vlia* zmE;%1=cJaU=77T)8obZZy@wn)DBi2eEYK}ZOiKj^2qTjSGw!qwv=t1NG=eDPlpo-Y z(1|U9LG&>&ENMK7suNiwwzP!MC=85NY$*%f1Z0nbQUMGsX`GF00=6`PZWMZwKp1rs z*(g{7LD!BRV+ie)Oh|q~i9d8RkbMJ+HW*maxC7Y?SR@8`v$BDdumj;Cpc`KS6)`XX E0770`LI3~& diff --git a/setup.py b/setup.py index 3500ad8c..a66118f1 100644 --- a/setup.py +++ b/setup.py @@ -117,6 +117,5 @@ setup( [console_scripts] flask=flask.cli:main ''', - cmdclass={'audit': run_audit}, - test_suite='flask.testsuite.suite' + cmdclass={'audit': run_audit} ) diff --git a/flask/testsuite/__init__.py b/tests/__init__.py similarity index 100% rename from flask/testsuite/__init__.py rename to tests/__init__.py diff --git a/flask/testsuite/appctx.py b/tests/appctx.py similarity index 100% rename from flask/testsuite/appctx.py rename to tests/appctx.py diff --git a/flask/testsuite/basic.py b/tests/basic.py similarity index 100% rename from flask/testsuite/basic.py rename to tests/basic.py diff --git a/flask/testsuite/blueprints.py b/tests/blueprints.py similarity index 100% rename from flask/testsuite/blueprints.py rename to tests/blueprints.py diff --git a/flask/testsuite/config.py b/tests/config.py similarity index 100% rename from flask/testsuite/config.py rename to tests/config.py diff --git a/flask/testsuite/deprecations.py b/tests/deprecations.py similarity index 100% rename from flask/testsuite/deprecations.py rename to tests/deprecations.py diff --git a/flask/testsuite/examples.py b/tests/examples.py similarity index 100% rename from flask/testsuite/examples.py rename to tests/examples.py diff --git a/flask/testsuite/ext.py b/tests/ext.py similarity index 100% rename from flask/testsuite/ext.py rename to tests/ext.py diff --git a/flask/testsuite/helpers.py b/tests/helpers.py similarity index 100% rename from flask/testsuite/helpers.py rename to tests/helpers.py diff --git a/flask/testsuite/regression.py b/tests/regression.py similarity index 100% rename from flask/testsuite/regression.py rename to tests/regression.py diff --git a/flask/testsuite/reqctx.py b/tests/reqctx.py similarity index 100% rename from flask/testsuite/reqctx.py rename to tests/reqctx.py diff --git a/flask/testsuite/signals.py b/tests/signals.py similarity index 100% rename from flask/testsuite/signals.py rename to tests/signals.py diff --git a/flask/testsuite/static/config.json b/tests/static/config.json similarity index 100% rename from flask/testsuite/static/config.json rename to tests/static/config.json diff --git a/flask/testsuite/static/index.html b/tests/static/index.html similarity index 100% rename from flask/testsuite/static/index.html rename to tests/static/index.html diff --git a/flask/testsuite/subclassing.py b/tests/subclassing.py similarity index 100% rename from flask/testsuite/subclassing.py rename to tests/subclassing.py diff --git a/flask/testsuite/templates/_macro.html b/tests/templates/_macro.html similarity index 100% rename from flask/testsuite/templates/_macro.html rename to tests/templates/_macro.html diff --git a/flask/testsuite/templates/context_template.html b/tests/templates/context_template.html similarity index 100% rename from flask/testsuite/templates/context_template.html rename to tests/templates/context_template.html diff --git a/flask/testsuite/templates/escaping_template.html b/tests/templates/escaping_template.html similarity index 100% rename from flask/testsuite/templates/escaping_template.html rename to tests/templates/escaping_template.html diff --git a/flask/testsuite/templates/mail.txt b/tests/templates/mail.txt similarity index 100% rename from flask/testsuite/templates/mail.txt rename to tests/templates/mail.txt diff --git a/flask/testsuite/templates/nested/nested.txt b/tests/templates/nested/nested.txt similarity index 100% rename from flask/testsuite/templates/nested/nested.txt rename to tests/templates/nested/nested.txt diff --git a/flask/testsuite/templates/simple_template.html b/tests/templates/simple_template.html similarity index 100% rename from flask/testsuite/templates/simple_template.html rename to tests/templates/simple_template.html diff --git a/flask/testsuite/templates/template_filter.html b/tests/templates/template_filter.html similarity index 100% rename from flask/testsuite/templates/template_filter.html rename to tests/templates/template_filter.html diff --git a/flask/testsuite/templates/template_test.html b/tests/templates/template_test.html similarity index 100% rename from flask/testsuite/templates/template_test.html rename to tests/templates/template_test.html diff --git a/flask/testsuite/templating.py b/tests/templating.py similarity index 100% rename from flask/testsuite/templating.py rename to tests/templating.py diff --git a/flask/testsuite/test_apps/blueprintapp/__init__.py b/tests/test_apps/blueprintapp/__init__.py similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/__init__.py rename to tests/test_apps/blueprintapp/__init__.py diff --git a/flask/testsuite/test_apps/blueprintapp/apps/__init__.py b/tests/test_apps/blueprintapp/apps/__init__.py similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/__init__.py rename to tests/test_apps/blueprintapp/apps/__init__.py diff --git a/flask/testsuite/test_apps/blueprintapp/apps/admin/__init__.py b/tests/test_apps/blueprintapp/apps/admin/__init__.py similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/admin/__init__.py rename to tests/test_apps/blueprintapp/apps/admin/__init__.py diff --git a/flask/testsuite/test_apps/blueprintapp/apps/admin/static/css/test.css b/tests/test_apps/blueprintapp/apps/admin/static/css/test.css similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/admin/static/css/test.css rename to tests/test_apps/blueprintapp/apps/admin/static/css/test.css diff --git a/flask/testsuite/test_apps/blueprintapp/apps/admin/static/test.txt b/tests/test_apps/blueprintapp/apps/admin/static/test.txt similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/admin/static/test.txt rename to tests/test_apps/blueprintapp/apps/admin/static/test.txt diff --git a/flask/testsuite/test_apps/blueprintapp/apps/admin/templates/admin/index.html b/tests/test_apps/blueprintapp/apps/admin/templates/admin/index.html similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/admin/templates/admin/index.html rename to tests/test_apps/blueprintapp/apps/admin/templates/admin/index.html diff --git a/flask/testsuite/test_apps/blueprintapp/apps/frontend/__init__.py b/tests/test_apps/blueprintapp/apps/frontend/__init__.py similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/frontend/__init__.py rename to tests/test_apps/blueprintapp/apps/frontend/__init__.py diff --git a/flask/testsuite/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html b/tests/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html similarity index 100% rename from flask/testsuite/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html rename to tests/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html diff --git a/flask/testsuite/test_apps/config_module_app.py b/tests/test_apps/config_module_app.py similarity index 100% rename from flask/testsuite/test_apps/config_module_app.py rename to tests/test_apps/config_module_app.py diff --git a/flask/testsuite/test_apps/config_package_app/__init__.py b/tests/test_apps/config_package_app/__init__.py similarity index 100% rename from flask/testsuite/test_apps/config_package_app/__init__.py rename to tests/test_apps/config_package_app/__init__.py diff --git a/flask/testsuite/test_apps/flask_broken/__init__.py b/tests/test_apps/flask_broken/__init__.py similarity index 100% rename from flask/testsuite/test_apps/flask_broken/__init__.py rename to tests/test_apps/flask_broken/__init__.py diff --git a/flask/testsuite/test_apps/flask_broken/b.py b/tests/test_apps/flask_broken/b.py similarity index 100% rename from flask/testsuite/test_apps/flask_broken/b.py rename to tests/test_apps/flask_broken/b.py diff --git a/flask/testsuite/test_apps/flask_newext_package/__init__.py b/tests/test_apps/flask_newext_package/__init__.py similarity index 100% rename from flask/testsuite/test_apps/flask_newext_package/__init__.py rename to tests/test_apps/flask_newext_package/__init__.py diff --git a/flask/testsuite/test_apps/flask_newext_package/submodule.py b/tests/test_apps/flask_newext_package/submodule.py similarity index 100% rename from flask/testsuite/test_apps/flask_newext_package/submodule.py rename to tests/test_apps/flask_newext_package/submodule.py diff --git a/flask/testsuite/test_apps/flask_newext_simple.py b/tests/test_apps/flask_newext_simple.py similarity index 100% rename from flask/testsuite/test_apps/flask_newext_simple.py rename to tests/test_apps/flask_newext_simple.py diff --git a/flask/testsuite/test_apps/flaskext/__init__.py b/tests/test_apps/flaskext/__init__.py similarity index 100% rename from flask/testsuite/test_apps/flaskext/__init__.py rename to tests/test_apps/flaskext/__init__.py diff --git a/flask/testsuite/test_apps/flaskext/oldext_package/__init__.py b/tests/test_apps/flaskext/oldext_package/__init__.py similarity index 100% rename from flask/testsuite/test_apps/flaskext/oldext_package/__init__.py rename to tests/test_apps/flaskext/oldext_package/__init__.py diff --git a/flask/testsuite/test_apps/flaskext/oldext_package/submodule.py b/tests/test_apps/flaskext/oldext_package/submodule.py similarity index 100% rename from flask/testsuite/test_apps/flaskext/oldext_package/submodule.py rename to tests/test_apps/flaskext/oldext_package/submodule.py diff --git a/flask/testsuite/test_apps/flaskext/oldext_simple.py b/tests/test_apps/flaskext/oldext_simple.py similarity index 100% rename from flask/testsuite/test_apps/flaskext/oldext_simple.py rename to tests/test_apps/flaskext/oldext_simple.py diff --git a/flask/testsuite/test_apps/importerror.py b/tests/test_apps/importerror.py similarity index 100% rename from flask/testsuite/test_apps/importerror.py rename to tests/test_apps/importerror.py diff --git a/flask/testsuite/test_apps/lib/python2.5/site-packages/site_app.py b/tests/test_apps/lib/python2.5/site-packages/site_app.py similarity index 100% rename from flask/testsuite/test_apps/lib/python2.5/site-packages/site_app.py rename to tests/test_apps/lib/python2.5/site-packages/site_app.py diff --git a/flask/testsuite/test_apps/lib/python2.5/site-packages/site_package/__init__.py b/tests/test_apps/lib/python2.5/site-packages/site_package/__init__.py similarity index 100% rename from flask/testsuite/test_apps/lib/python2.5/site-packages/site_package/__init__.py rename to tests/test_apps/lib/python2.5/site-packages/site_package/__init__.py diff --git a/flask/testsuite/test_apps/main_app.py b/tests/test_apps/main_app.py similarity index 100% rename from flask/testsuite/test_apps/main_app.py rename to tests/test_apps/main_app.py diff --git a/flask/testsuite/test_apps/path/installed_package/__init__.py b/tests/test_apps/path/installed_package/__init__.py similarity index 100% rename from flask/testsuite/test_apps/path/installed_package/__init__.py rename to tests/test_apps/path/installed_package/__init__.py diff --git a/flask/testsuite/test_apps/subdomaintestmodule/__init__.py b/tests/test_apps/subdomaintestmodule/__init__.py similarity index 100% rename from flask/testsuite/test_apps/subdomaintestmodule/__init__.py rename to tests/test_apps/subdomaintestmodule/__init__.py diff --git a/flask/testsuite/test_apps/subdomaintestmodule/static/hello.txt b/tests/test_apps/subdomaintestmodule/static/hello.txt similarity index 100% rename from flask/testsuite/test_apps/subdomaintestmodule/static/hello.txt rename to tests/test_apps/subdomaintestmodule/static/hello.txt diff --git a/flask/testsuite/testing.py b/tests/testing.py similarity index 100% rename from flask/testsuite/testing.py rename to tests/testing.py diff --git a/flask/testsuite/views.py b/tests/views.py similarity index 100% rename from flask/testsuite/views.py rename to tests/views.py From 961db8ad7290f1bd91058b11a5de31e27bf28563 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 31 Aug 2014 21:54:45 +0200 Subject: [PATCH 03/33] Made tests recognizable --- tests/__init__.py | 2 +- tests/{appctx.py => test_appctx.py} | 4 ++-- tests/{basic.py => test_basic.py} | 4 ++-- tests/{blueprints.py => test_blueprints.py} | 4 ++-- tests/{config.py => test_config.py} | 4 ++-- tests/{deprecations.py => test_deprecations.py} | 4 ++-- tests/{examples.py => test_examples.py} | 4 ++-- tests/{ext.py => test_ext.py} | 4 ++-- tests/{helpers.py => test_helpers.py} | 4 ++-- tests/{regression.py => test_regression.py} | 4 ++-- tests/{reqctx.py => test_reqctx.py} | 4 ++-- tests/{signals.py => test_signals.py} | 4 ++-- tests/{subclassing.py => test_subclassing.py} | 4 ++-- tests/{templating.py => test_templating.py} | 4 ++-- tests/{testing.py => test_testing.py} | 4 ++-- tests/{views.py => test_views.py} | 4 ++-- 16 files changed, 31 insertions(+), 31 deletions(-) rename tests/{appctx.py => test_appctx.py} (98%) rename tests/{basic.py => test_basic.py} (99%) rename tests/{blueprints.py => test_blueprints.py} (99%) rename tests/{config.py => test_config.py} (99%) rename tests/{deprecations.py => test_deprecations.py} (82%) rename tests/{examples.py => test_examples.py} (92%) rename tests/{ext.py => test_ext.py} (98%) rename tests/{helpers.py => test_helpers.py} (99%) rename tests/{regression.py => test_regression.py} (97%) rename tests/{reqctx.py => test_reqctx.py} (98%) rename tests/{signals.py => test_signals.py} (98%) rename tests/{subclassing.py => test_subclassing.py} (93%) rename tests/{templating.py => test_templating.py} (99%) rename tests/{testing.py => test_testing.py} (99%) rename tests/{views.py => test_views.py} (98%) diff --git a/tests/__init__.py b/tests/__init__.py index 0ed17c30..2d1b979d 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite + tests ~~~~~~~~~~~~~~~ Tests Flask itself. The majority of Flask is already tested diff --git a/tests/appctx.py b/tests/test_appctx.py similarity index 98% rename from tests/appctx.py rename to tests/test_appctx.py index 55f7dcba..65e9e86d 100644 --- a/tests/appctx.py +++ b/tests/test_appctx.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.appctx + tests.appctx ~~~~~~~~~~~~~~~~~~~~~~ Tests the application context. @@ -11,7 +11,7 @@ import flask import unittest -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase class AppContextTestCase(FlaskTestCase): diff --git a/tests/basic.py b/tests/test_basic.py similarity index 99% rename from tests/basic.py rename to tests/test_basic.py index 6c2525f9..1cc20ee0 100644 --- a/tests/basic.py +++ b/tests/test_basic.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.basic + tests.basic ~~~~~~~~~~~~~~~~~~~~~ The basic functionality. @@ -17,7 +17,7 @@ import pickle import unittest from datetime import datetime from threading import Thread -from flask.testsuite import FlaskTestCase, emits_module_deprecation_warning +from tests import FlaskTestCase, emits_module_deprecation_warning from flask._compat import text_type from werkzeug.exceptions import BadRequest, NotFound, Forbidden from werkzeug.http import parse_date diff --git a/tests/blueprints.py b/tests/test_blueprints.py similarity index 99% rename from tests/blueprints.py rename to tests/test_blueprints.py index 8d3224a3..a5488a57 100644 --- a/tests/blueprints.py +++ b/tests/test_blueprints.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.blueprints + tests.blueprints ~~~~~~~~~~~~~~~~~~~~~~~~~~ Blueprints (and currently modules) @@ -11,7 +11,7 @@ import flask import unittest -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase from flask._compat import text_type from werkzeug.http import parse_cache_control_header from jinja2 import TemplateNotFound diff --git a/tests/config.py b/tests/test_config.py similarity index 99% rename from tests/config.py rename to tests/test_config.py index 4772fa77..4f9e693f 100644 --- a/tests/config.py +++ b/tests/test_config.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.config + tests.config ~~~~~~~~~~~~~~~~~~~~~~ Configuration and instances. @@ -15,7 +15,7 @@ import flask import pkgutil import unittest from contextlib import contextmanager -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase from flask._compat import PY2 diff --git a/tests/deprecations.py b/tests/test_deprecations.py similarity index 82% rename from tests/deprecations.py rename to tests/test_deprecations.py index 2d77925e..7353af5a 100644 --- a/tests/deprecations.py +++ b/tests/test_deprecations.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.deprecations + tests.deprecations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tests deprecation support. @@ -11,7 +11,7 @@ import flask import unittest -from flask.testsuite import FlaskTestCase, catch_warnings +from tests import FlaskTestCase, catch_warnings class DeprecationsTestCase(FlaskTestCase): diff --git a/tests/examples.py b/tests/test_examples.py similarity index 92% rename from tests/examples.py rename to tests/test_examples.py index 1ea3e6cc..c321a141 100644 --- a/tests/examples.py +++ b/tests/test_examples.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.examples + tests.examples ~~~~~~~~~~~~~~~~~~~~~~~~ Tests the examples. @@ -10,7 +10,7 @@ """ import os import unittest -from flask.testsuite import add_to_path +from tests import add_to_path def setup_path(): diff --git a/tests/ext.py b/tests/test_ext.py similarity index 98% rename from tests/ext.py rename to tests/test_ext.py index 5ec6ec63..110657d8 100644 --- a/tests/ext.py +++ b/tests/test_ext.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.ext + tests.ext ~~~~~~~~~~~~~~~~~~~ Tests the extension import thing. @@ -15,7 +15,7 @@ try: from imp import reload as reload_module except ImportError: reload_module = reload -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase from flask._compat import PY2 class ExtImportHookTestCase(FlaskTestCase): diff --git a/tests/helpers.py b/tests/test_helpers.py similarity index 99% rename from tests/helpers.py rename to tests/test_helpers.py index e08a2283..c923cae1 100644 --- a/tests/helpers.py +++ b/tests/test_helpers.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.helpers + tests.helpers ~~~~~~~~~~~~~~~~~~~~~~~ Various helpers. @@ -13,7 +13,7 @@ import os import flask import unittest from logging import StreamHandler -from flask.testsuite import FlaskTestCase, catch_warnings, catch_stderr +from tests import FlaskTestCase, catch_warnings, catch_stderr from werkzeug.http import parse_cache_control_header, parse_options_header from flask._compat import StringIO, text_type diff --git a/tests/regression.py b/tests/test_regression.py similarity index 97% rename from tests/regression.py rename to tests/test_regression.py index ad06aa59..8bdbbf6d 100644 --- a/tests/regression.py +++ b/tests/test_regression.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.regression + tests.regression ~~~~~~~~~~~~~~~~~~~~~~~~~~ Tests regressions. @@ -16,7 +16,7 @@ import flask import threading import unittest from werkzeug.exceptions import NotFound -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase _gc_lock = threading.Lock() diff --git a/tests/reqctx.py b/tests/test_reqctx.py similarity index 98% rename from tests/reqctx.py rename to tests/test_reqctx.py index c8954824..4ea04098 100644 --- a/tests/reqctx.py +++ b/tests/test_reqctx.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.reqctx + tests.reqctx ~~~~~~~~~~~~~~~~~~~~~~ Tests the request context. @@ -15,7 +15,7 @@ try: from greenlet import greenlet except ImportError: greenlet = None -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase class RequestContextTestCase(FlaskTestCase): diff --git a/tests/signals.py b/tests/test_signals.py similarity index 98% rename from tests/signals.py rename to tests/test_signals.py index 93f1c7c8..d05b5b27 100644 --- a/tests/signals.py +++ b/tests/test_signals.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.signals + tests.signals ~~~~~~~~~~~~~~~~~~~~~~~ Signalling. @@ -11,7 +11,7 @@ import flask import unittest -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase class SignalsTestCase(FlaskTestCase): diff --git a/tests/subclassing.py b/tests/test_subclassing.py similarity index 93% rename from tests/subclassing.py rename to tests/test_subclassing.py index 24c823ae..41e587e7 100644 --- a/tests/subclassing.py +++ b/tests/test_subclassing.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.subclassing + tests.subclassing ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Test that certain behavior of flask can be customized by @@ -12,7 +12,7 @@ import flask import unittest from logging import StreamHandler -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase from flask._compat import StringIO diff --git a/tests/templating.py b/tests/test_templating.py similarity index 99% rename from tests/templating.py rename to tests/test_templating.py index 435ace21..5ce67d97 100644 --- a/tests/templating.py +++ b/tests/test_templating.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.templating + tests.templating ~~~~~~~~~~~~~~~~~~~~~~~~~~ Template functionality @@ -14,7 +14,7 @@ import unittest import logging from jinja2 import TemplateNotFound -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase class TemplatingTestCase(FlaskTestCase): diff --git a/tests/testing.py b/tests/test_testing.py similarity index 99% rename from tests/testing.py rename to tests/test_testing.py index 25924839..3a51c59f 100644 --- a/tests/testing.py +++ b/tests/test_testing.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.testing + tests.testing ~~~~~~~~~~~~~~~~~~~~~~~ Test client and more. @@ -11,7 +11,7 @@ import flask import unittest -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase from flask._compat import text_type diff --git a/tests/views.py b/tests/test_views.py similarity index 98% rename from tests/views.py rename to tests/test_views.py index bd572b24..f98f920b 100644 --- a/tests/views.py +++ b/tests/test_views.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ - flask.testsuite.views + tests.views ~~~~~~~~~~~~~~~~~~~~~ Pluggable views. @@ -12,7 +12,7 @@ import flask import flask.views import unittest -from flask.testsuite import FlaskTestCase +from tests import FlaskTestCase from werkzeug.http import parse_set_header class ViewTestCase(FlaskTestCase): From 8fa5e32d9a1fdf042632bd8fcd0b44dd8031b639 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 31 Aug 2014 21:56:15 +0200 Subject: [PATCH 04/33] Tests pass now. --- .../blueprintexample/blueprintexample_test.py | 36 ---- .../blueprintexample/test_blueprintexample.py | 33 ++++ examples/flaskr/flaskr_tests.py | 76 -------- examples/flaskr/test_flaskr.py | 77 ++++++++ examples/minitwit/minitwit_tests.py | 150 ---------------- examples/minitwit/test_minitwit.py | 151 ++++++++++++++++ setup.cfg | 3 + tests/__init__.py | 169 ++++-------------- tests/test_appctx.py | 8 +- tests/test_apps/importerror.py | 2 +- tests/test_basic.py | 47 +++-- tests/test_blueprints.py | 22 +-- tests/test_config.py | 16 +- tests/test_deprecations.py | 6 +- tests/test_examples.py | 8 +- tests/test_ext.py | 6 +- tests/test_helpers.py | 34 ++-- tests/test_regression.py | 27 ++- tests/test_reqctx.py | 6 +- tests/test_signals.py | 6 +- tests/test_subclassing.py | 6 +- tests/test_templating.py | 6 +- tests/test_testing.py | 50 +++--- tests/test_views.py | 6 +- 24 files changed, 421 insertions(+), 530 deletions(-) delete mode 100644 examples/blueprintexample/blueprintexample_test.py create mode 100644 examples/blueprintexample/test_blueprintexample.py delete mode 100644 examples/flaskr/flaskr_tests.py create mode 100644 examples/flaskr/test_flaskr.py delete mode 100644 examples/minitwit/minitwit_tests.py create mode 100644 examples/minitwit/test_minitwit.py diff --git a/examples/blueprintexample/blueprintexample_test.py b/examples/blueprintexample/blueprintexample_test.py deleted file mode 100644 index b8f93414..00000000 --- a/examples/blueprintexample/blueprintexample_test.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -""" - Blueprint Example Tests - ~~~~~~~~~~~~~~ - - Tests the Blueprint example app -""" -import blueprintexample -import unittest - - -class BlueprintExampleTestCase(unittest.TestCase): - - def setUp(self): - self.app = blueprintexample.app.test_client() - - def test_urls(self): - r = self.app.get('/') - self.assertEquals(r.status_code, 200) - - r = self.app.get('/hello') - self.assertEquals(r.status_code, 200) - - r = self.app.get('/world') - self.assertEquals(r.status_code, 200) - - #second blueprint instance - r = self.app.get('/pages/hello') - self.assertEquals(r.status_code, 200) - - r = self.app.get('/pages/world') - self.assertEquals(r.status_code, 200) - - -if __name__ == '__main__': - unittest.main() diff --git a/examples/blueprintexample/test_blueprintexample.py b/examples/blueprintexample/test_blueprintexample.py new file mode 100644 index 00000000..2f3dd93f --- /dev/null +++ b/examples/blueprintexample/test_blueprintexample.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +""" + Blueprint Example Tests + ~~~~~~~~~~~~~~ + + Tests the Blueprint example app +""" +import pytest + +import blueprintexample + + +@pytest.fixture +def client(): + return blueprintexample.app.test_client() + + +def test_urls(client): + r = client.get('/') + assert r.status_code == 200 + + r = client.get('/hello') + assert r.status_code == 200 + + r = client.get('/world') + assert r.status_code == 200 + + # second blueprint instance + r = client.get('/pages/hello') + assert r.status_code == 200 + + r = client.get('/pages/world') + assert r.status_code == 200 diff --git a/examples/flaskr/flaskr_tests.py b/examples/flaskr/flaskr_tests.py deleted file mode 100644 index b90a7be7..00000000 --- a/examples/flaskr/flaskr_tests.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -""" - Flaskr Tests - ~~~~~~~~~~~~ - - Tests the Flaskr application. - - :copyright: (c) 2014 by Armin Ronacher. - :license: BSD, see LICENSE for more details. -""" -import os -import flaskr -import unittest -import tempfile - - -class FlaskrTestCase(unittest.TestCase): - - def setUp(self): - """Before each test, set up a blank database""" - self.db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp() - flaskr.app.config['TESTING'] = True - self.app = flaskr.app.test_client() - with flaskr.app.app_context(): - flaskr.init_db() - - def tearDown(self): - """Get rid of the database again after each test.""" - os.close(self.db_fd) - os.unlink(flaskr.app.config['DATABASE']) - - def login(self, username, password): - return self.app.post('/login', data=dict( - username=username, - password=password - ), follow_redirects=True) - - def logout(self): - return self.app.get('/logout', follow_redirects=True) - - # testing functions - - def test_empty_db(self): - """Start with a blank database.""" - rv = self.app.get('/') - assert b'No entries here so far' in rv.data - - def test_login_logout(self): - """Make sure login and logout works""" - rv = self.login(flaskr.app.config['USERNAME'], - flaskr.app.config['PASSWORD']) - assert b'You were logged in' in rv.data - rv = self.logout() - assert b'You were logged out' in rv.data - rv = self.login(flaskr.app.config['USERNAME'] + 'x', - flaskr.app.config['PASSWORD']) - assert b'Invalid username' in rv.data - rv = self.login(flaskr.app.config['USERNAME'], - flaskr.app.config['PASSWORD'] + 'x') - assert b'Invalid password' in rv.data - - def test_messages(self): - """Test that messages work""" - self.login(flaskr.app.config['USERNAME'], - flaskr.app.config['PASSWORD']) - rv = self.app.post('/add', data=dict( - title='', - text='HTML allowed here' - ), follow_redirects=True) - assert b'No entries here so far' not in rv.data - assert b'<Hello>' in rv.data - assert b'HTML allowed here' in rv.data - - -if __name__ == '__main__': - unittest.main() diff --git a/examples/flaskr/test_flaskr.py b/examples/flaskr/test_flaskr.py new file mode 100644 index 00000000..07116f81 --- /dev/null +++ b/examples/flaskr/test_flaskr.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +""" + Flaskr Tests + ~~~~~~~~~~~~ + + Tests the Flaskr application. + + :copyright: (c) 2014 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import pytest + +import os +import flaskr +import tempfile + + +@pytest.fixture +def client(request): + db_fd, flaskr.app.config['DATABASE'] = tempfile.mkstemp() + flaskr.app.config['TESTING'] = True + client = flaskr.app.test_client() + with flaskr.app.app_context(): + flaskr.init_db() + + def teardown(): + os.close(db_fd) + os.unlink(flaskr.app.config['DATABASE']) + request.addfinalizer(teardown) + + return client + + +def login(client, username, password): + return client.post('/login', data=dict( + username=username, + password=password + ), follow_redirects=True) + + +def logout(client): + return client.get('/logout', follow_redirects=True) + + +def test_empty_db(client): + """Start with a blank database.""" + rv = client.get('/') + assert b'No entries here so far' in rv.data + + +def test_login_logout(client): + """Make sure login and logout works""" + rv = login(client, flaskr.app.config['USERNAME'], + flaskr.app.config['PASSWORD']) + assert b'You were logged in' in rv.data + rv = logout(client) + assert b'You were logged out' in rv.data + rv = login(client, flaskr.app.config['USERNAME'] + 'x', + flaskr.app.config['PASSWORD']) + assert b'Invalid username' in rv.data + rv = login(client, flaskr.app.config['USERNAME'], + flaskr.app.config['PASSWORD'] + 'x') + assert b'Invalid password' in rv.data + + +def test_messages(client): + """Test that messages work""" + login(client, flaskr.app.config['USERNAME'], + flaskr.app.config['PASSWORD']) + rv = client.post('/add', data=dict( + title='', + text='HTML allowed here' + ), follow_redirects=True) + assert b'No entries here so far' not in rv.data + assert b'<Hello>' in rv.data + assert b'HTML allowed here' in rv.data diff --git a/examples/minitwit/minitwit_tests.py b/examples/minitwit/minitwit_tests.py deleted file mode 100644 index 0a1a3f67..00000000 --- a/examples/minitwit/minitwit_tests.py +++ /dev/null @@ -1,150 +0,0 @@ -# -*- coding: utf-8 -*- -""" - MiniTwit Tests - ~~~~~~~~~~~~~~ - - Tests the MiniTwit application. - - :copyright: (c) 2014 by Armin Ronacher. - :license: BSD, see LICENSE for more details. -""" -import os -import minitwit -import unittest -import tempfile - - -class MiniTwitTestCase(unittest.TestCase): - - def setUp(self): - """Before each test, set up a blank database""" - self.db_fd, minitwit.app.config['DATABASE'] = tempfile.mkstemp() - self.app = minitwit.app.test_client() - with minitwit.app.app_context(): - minitwit.init_db() - - def tearDown(self): - """Get rid of the database again after each test.""" - os.close(self.db_fd) - os.unlink(minitwit.app.config['DATABASE']) - - # helper functions - - def register(self, username, password, password2=None, email=None): - """Helper function to register a user""" - if password2 is None: - password2 = password - if email is None: - email = username + '@example.com' - return self.app.post('/register', data={ - 'username': username, - 'password': password, - 'password2': password2, - 'email': email, - }, follow_redirects=True) - - def login(self, username, password): - """Helper function to login""" - return self.app.post('/login', data={ - 'username': username, - 'password': password - }, follow_redirects=True) - - def register_and_login(self, username, password): - """Registers and logs in in one go""" - self.register(username, password) - return self.login(username, password) - - def logout(self): - """Helper function to logout""" - return self.app.get('/logout', follow_redirects=True) - - def add_message(self, text): - """Records a message""" - rv = self.app.post('/add_message', data={'text': text}, - follow_redirects=True) - if text: - assert b'Your message was recorded' in rv.data - return rv - - # testing functions - - def test_register(self): - """Make sure registering works""" - rv = self.register('user1', 'default') - assert b'You were successfully registered ' \ - b'and can login now' in rv.data - rv = self.register('user1', 'default') - assert b'The username is already taken' in rv.data - rv = self.register('', 'default') - assert b'You have to enter a username' in rv.data - rv = self.register('meh', '') - assert b'You have to enter a password' in rv.data - rv = self.register('meh', 'x', 'y') - assert b'The two passwords do not match' in rv.data - rv = self.register('meh', 'foo', email='broken') - assert b'You have to enter a valid email address' in rv.data - - def test_login_logout(self): - """Make sure logging in and logging out works""" - rv = self.register_and_login('user1', 'default') - assert b'You were logged in' in rv.data - rv = self.logout() - assert b'You were logged out' in rv.data - rv = self.login('user1', 'wrongpassword') - assert b'Invalid password' in rv.data - rv = self.login('user2', 'wrongpassword') - assert b'Invalid username' in rv.data - - def test_message_recording(self): - """Check if adding messages works""" - self.register_and_login('foo', 'default') - self.add_message('test message 1') - self.add_message('') - rv = self.app.get('/') - assert b'test message 1' in rv.data - assert b'<test message 2>' in rv.data - - def test_timelines(self): - """Make sure that timelines work""" - self.register_and_login('foo', 'default') - self.add_message('the message by foo') - self.logout() - self.register_and_login('bar', 'default') - self.add_message('the message by bar') - rv = self.app.get('/public') - assert b'the message by foo' in rv.data - assert b'the message by bar' in rv.data - - # bar's timeline should just show bar's message - rv = self.app.get('/') - assert b'the message by foo' not in rv.data - assert b'the message by bar' in rv.data - - # now let's follow foo - rv = self.app.get('/foo/follow', follow_redirects=True) - assert b'You are now following "foo"' in rv.data - - # we should now see foo's message - rv = self.app.get('/') - assert b'the message by foo' in rv.data - assert b'the message by bar' in rv.data - - # but on the user's page we only want the user's message - rv = self.app.get('/bar') - assert b'the message by foo' not in rv.data - assert b'the message by bar' in rv.data - rv = self.app.get('/foo') - assert b'the message by foo' in rv.data - assert b'the message by bar' not in rv.data - - # now unfollow and check if that worked - rv = self.app.get('/foo/unfollow', follow_redirects=True) - assert b'You are no longer following "foo"' in rv.data - rv = self.app.get('/') - assert b'the message by foo' not in rv.data - assert b'the message by bar' in rv.data - - -if __name__ == '__main__': - unittest.main() diff --git a/examples/minitwit/test_minitwit.py b/examples/minitwit/test_minitwit.py new file mode 100644 index 00000000..c9345e9d --- /dev/null +++ b/examples/minitwit/test_minitwit.py @@ -0,0 +1,151 @@ +# -*- coding: utf-8 -*- +""" + MiniTwit Tests + ~~~~~~~~~~~~~~ + + Tests the MiniTwit application. + + :copyright: (c) 2014 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import os +import minitwit +import tempfile +import pytest + + +@pytest.fixture +def client(request): + db_fd, minitwit.app.config['DATABASE'] = tempfile.mkstemp() + client = minitwit.app.test_client() + with minitwit.app.app_context(): + minitwit.init_db() + + def teardown(): + """Get rid of the database again after each test.""" + os.close(db_fd) + os.unlink(minitwit.app.config['DATABASE']) + request.addfinalizer(teardown) + return client + + +def register(client, username, password, password2=None, email=None): + """Helper function to register a user""" + if password2 is None: + password2 = password + if email is None: + email = username + '@example.com' + return client.post('/register', data={ + 'username': username, + 'password': password, + 'password2': password2, + 'email': email, + }, follow_redirects=True) + + +def login(client, username, password): + """Helper function to login""" + return client.post('/login', data={ + 'username': username, + 'password': password + }, follow_redirects=True) + + +def register_and_login(client, username, password): + """Registers and logs in in one go""" + register(client, username, password) + return login(client, username, password) + + +def logout(client): + """Helper function to logout""" + return client.get('/logout', follow_redirects=True) + + +def add_message(client, text): + """Records a message""" + rv = client.post('/add_message', data={'text': text}, + follow_redirects=True) + if text: + assert b'Your message was recorded' in rv.data + return rv + + +def test_register(client): + """Make sure registering works""" + rv = register(client, 'user1', 'default') + assert b'You were successfully registered ' \ + b'and can login now' in rv.data + rv = register(client, 'user1', 'default') + assert b'The username is already taken' in rv.data + rv = register(client, '', 'default') + assert b'You have to enter a username' in rv.data + rv = register(client, 'meh', '') + assert b'You have to enter a password' in rv.data + rv = register(client, 'meh', 'x', 'y') + assert b'The two passwords do not match' in rv.data + rv = register(client, 'meh', 'foo', email='broken') + assert b'You have to enter a valid email address' in rv.data + + +def test_login_logout(client): + """Make sure logging in and logging out works""" + rv = register_and_login(client, 'user1', 'default') + assert b'You were logged in' in rv.data + rv = logout(client) + assert b'You were logged out' in rv.data + rv = login(client, 'user1', 'wrongpassword') + assert b'Invalid password' in rv.data + rv = login(client, 'user2', 'wrongpassword') + assert b'Invalid username' in rv.data + + +def test_message_recording(client): + """Check if adding messages works""" + register_and_login(client, 'foo', 'default') + add_message(client, 'test message 1') + add_message(client, '') + rv = client.get('/') + assert b'test message 1' in rv.data + assert b'<test message 2>' in rv.data + + +def test_timelines(client): + """Make sure that timelines work""" + register_and_login(client, 'foo', 'default') + add_message(client, 'the message by foo') + logout(client) + register_and_login(client, 'bar', 'default') + add_message(client, 'the message by bar') + rv = client.get('/public') + assert b'the message by foo' in rv.data + assert b'the message by bar' in rv.data + + # bar's timeline should just show bar's message + rv = client.get('/') + assert b'the message by foo' not in rv.data + assert b'the message by bar' in rv.data + + # now let's follow foo + rv = client.get('/foo/follow', follow_redirects=True) + assert b'You are now following "foo"' in rv.data + + # we should now see foo's message + rv = client.get('/') + assert b'the message by foo' in rv.data + assert b'the message by bar' in rv.data + + # but on the user's page we only want the user's message + rv = client.get('/bar') + assert b'the message by foo' not in rv.data + assert b'the message by bar' in rv.data + rv = client.get('/foo') + assert b'the message by foo' in rv.data + assert b'the message by bar' not in rv.data + + # now unfollow and check if that worked + rv = client.get('/foo/unfollow', follow_redirects=True) + assert b'You are no longer following "foo"' in rv.data + rv = client.get('/') + assert b'the message by foo' not in rv.data + assert b'the message by bar' in rv.data diff --git a/setup.cfg b/setup.cfg index dbd1f97a..c3b4abda 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,6 @@ +[pytest] +norecursedirs= scripts docs + [aliases] release = egg_info -RDb '' diff --git a/tests/__init__.py b/tests/__init__.py index 2d1b979d..9c349854 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -11,16 +11,15 @@ """ from __future__ import print_function +import pytest import os import sys import flask import warnings -import unittest from functools import update_wrapper from contextlib import contextmanager -from werkzeug.utils import import_string, find_modules -from flask._compat import reraise, StringIO +from flask._compat import StringIO def add_to_path(path): @@ -43,29 +42,6 @@ def add_to_path(path): sys.path.insert(0, path) -def iter_suites(): - """Yields all testsuites.""" - for module in find_modules(__name__): - mod = import_string(module) - if hasattr(mod, 'suite'): - yield mod.suite() - - -def find_all_tests(suite): - """Yields all the tests and their names from a given suite.""" - suites = [suite] - while suites: - s = suites.pop() - try: - suites.extend(s) - except TypeError: - yield s, '%s.%s.%s' % ( - s.__class__.__module__, - s.__class__.__name__, - s._testMethodName - ) - - @contextmanager def catch_warnings(): """Catch warnings in a with block in a list""" @@ -76,6 +52,7 @@ def catch_warnings(): warnings.filters = filters[:] old_showwarning = warnings.showwarning log = [] + def showwarning(message, category, filename, lineno, file=None, line=None): log.append(locals()) try: @@ -107,12 +84,23 @@ def emits_module_deprecation_warning(f): return update_wrapper(new_f, f) -class FlaskTestCase(unittest.TestCase): +class TestFlask(object): """Baseclass for all the tests that Flask uses. Use these methods for testing instead of the camelcased ones in the baseclass for consistency. """ + @pytest.fixture(autouse=True) + def setup_path(self, monkeypatch): + monkeypatch.syspath_prepend( + os.path.abspath(os.path.join( + os.path.dirname(__file__), 'test_apps')) + ) + + @pytest.fixture(autouse=True) + def leak_detector(self, request): + request.addfinalizer(self.ensure_clean_request_context) + def ensure_clean_request_context(self): # make sure we're not leaking a request context since we are # testing flask internally in debug mode in a few cases @@ -121,133 +109,42 @@ class FlaskTestCase(unittest.TestCase): leaks.append(flask._request_ctx_stack.pop()) self.assert_equal(leaks, []) + def setup_method(self, method): + self.setup() + + def teardown_method(self, method): + self.teardown() + def setup(self): pass def teardown(self): pass - def setUp(self): - self.setup() - - def tearDown(self): - unittest.TestCase.tearDown(self) - self.ensure_clean_request_context() - self.teardown() - def assert_equal(self, x, y): - return self.assertEqual(x, y) + assert x == y def assert_raises(self, exc_type, callable=None, *args, **kwargs): - catcher = _ExceptionCatcher(self, exc_type) - if callable is None: - return catcher - with catcher: - callable(*args, **kwargs) + if callable: + return pytest.raises(exc_type, callable, *args, **kwargs) + else: + return pytest.raises(exc_type) def assert_true(self, x, msg=None): - self.assertTrue(x, msg) + assert x assert_ = assert_true def assert_false(self, x, msg=None): - self.assertFalse(x, msg) + assert not x def assert_in(self, x, y): - self.assertIn(x, y) + assert x in y def assert_not_in(self, x, y): - self.assertNotIn(x, y) + assert x not in y def assert_isinstance(self, obj, cls): - self.assertIsInstance(obj, cls) + assert isinstance(obj, cls) - if sys.version_info[:2] == (2, 6): - def assertIn(self, x, y): - assert x in y, "%r unexpectedly not in %r" % (x, y) - - def assertNotIn(self, x, y): - assert x not in y, "%r unexpectedly in %r" % (x, y) - - def assertIsInstance(self, x, y): - assert isinstance(x, y), "not isinstance(%r, %r)" % (x, y) - - -class _ExceptionCatcher(object): - - def __init__(self, test_case, exc_type): - self.test_case = test_case - self.exc_type = exc_type - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, tb): - exception_name = self.exc_type.__name__ - if exc_type is None: - self.test_case.fail('Expected exception of type %r' % - exception_name) - elif not issubclass(exc_type, self.exc_type): - reraise(exc_type, exc_value, tb) - return True - - -class BetterLoader(unittest.TestLoader): - """A nicer loader that solves two problems. First of all we are setting - up tests from different sources and we're doing this programmatically - which breaks the default loading logic so this is required anyways. - Secondly this loader has a nicer interpolation for test names than the - default one so you can just do ``run-tests.py ViewTestCase`` and it - will work. - """ - - def getRootSuite(self): - return suite() - - def loadTestsFromName(self, name, module=None): - root = self.getRootSuite() - if name == 'suite': - return root - - all_tests = [] - for testcase, testname in find_all_tests(root): - if testname == name or \ - testname.endswith('.' + name) or \ - ('.' + name + '.') in testname or \ - testname.startswith(name + '.'): - all_tests.append(testcase) - - if not all_tests: - raise LookupError('could not find test case for "%s"' % name) - - if len(all_tests) == 1: - return all_tests[0] - rv = unittest.TestSuite() - for test in all_tests: - rv.addTest(test) - return rv - - -def setup_path(): - add_to_path(os.path.abspath(os.path.join( - os.path.dirname(__file__), 'test_apps'))) - - -def suite(): - """A testsuite that has all the Flask tests. You can use this - function to integrate the Flask tests into your own testsuite - in case you want to test that monkeypatches to Flask do not - break it. - """ - setup_path() - suite = unittest.TestSuite() - for other_suite in iter_suites(): - suite.addTest(other_suite) - return suite - - -def main(): - """Runs the testsuite as command line application.""" - try: - unittest.main(testLoader=BetterLoader(), defaultTest='suite') - except Exception as e: - print('Error: %s' % e) + def fail(self, msg): + raise AssertionError(msg) diff --git a/tests/test_appctx.py b/tests/test_appctx.py index 65e9e86d..2430f577 100644 --- a/tests/test_appctx.py +++ b/tests/test_appctx.py @@ -11,10 +11,10 @@ import flask import unittest -from tests import FlaskTestCase +from tests import TestFlask -class AppContextTestCase(FlaskTestCase): +class TestAppContext(TestFlask): def test_basic_url_generation(self): app = flask.Flask(__name__) @@ -109,10 +109,10 @@ class AppContextTestCase(FlaskTestCase): return u'' c = app.test_client() c.get('/') - self.assertEqual(called, ['request', 'app']) + self.assert_equal(called, ['request', 'app']) def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(AppContextTestCase)) + suite.addTest(unittest.makeSuite(TestAppContext)) return suite diff --git a/tests/test_apps/importerror.py b/tests/test_apps/importerror.py index eb298b9b..3970e3e7 100644 --- a/tests/test_apps/importerror.py +++ b/tests/test_apps/importerror.py @@ -1,2 +1,2 @@ -# NoImportsTestCase +# TestNoImports raise NotImplementedError diff --git a/tests/test_basic.py b/tests/test_basic.py index 1cc20ee0..c06907e6 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -17,14 +17,14 @@ import pickle import unittest from datetime import datetime from threading import Thread -from tests import FlaskTestCase, emits_module_deprecation_warning +from tests import TestFlask, emits_module_deprecation_warning from flask._compat import text_type from werkzeug.exceptions import BadRequest, NotFound, Forbidden from werkzeug.http import parse_date from werkzeug.routing import BuildError -class BasicFunctionalityTestCase(FlaskTestCase): +class TestBasicFunctionality(TestFlask): def test_options_work(self): app = flask.Flask(__name__) @@ -522,8 +522,8 @@ class BasicFunctionalityTestCase(FlaskTestCase): return 'Test' c = app.test_client() resp = c.get('/') - self.assertEqual(resp.status_code, 200) - self.assertEqual(resp.headers['X-Foo'], 'a header') + self.assert_equal(resp.status_code, 200) + self.assert_equal(resp.headers['X-Foo'], 'a header') def test_teardown_request_handler(self): called = [] @@ -840,22 +840,22 @@ class BasicFunctionalityTestCase(FlaskTestCase): with app.test_request_context(): rv = flask.make_response( flask.jsonify({'msg': 'W00t'}), 400) - self.assertEqual(rv.status_code, 400) - self.assertEqual(rv.data, b'{\n "msg": "W00t"\n}') - self.assertEqual(rv.mimetype, 'application/json') + self.assert_equal(rv.status_code, 400) + self.assert_equal(rv.data, b'{\n "msg": "W00t"\n}') + self.assert_equal(rv.mimetype, 'application/json') rv = flask.make_response( flask.Response(''), 400) - self.assertEqual(rv.status_code, 400) - self.assertEqual(rv.data, b'') - self.assertEqual(rv.mimetype, 'text/html') + self.assert_equal(rv.status_code, 400) + self.assert_equal(rv.data, b'') + self.assert_equal(rv.mimetype, 'text/html') rv = flask.make_response( flask.Response('', headers={'Content-Type': 'text/html'}), 400, [('X-Foo', 'bar')]) - self.assertEqual(rv.status_code, 400) - self.assertEqual(rv.headers['Content-Type'], 'text/html') - self.assertEqual(rv.headers['X-Foo'], 'bar') + self.assert_equal(rv.status_code, 400) + self.assert_equal(rv.headers['Content-Type'], 'text/html') + self.assert_equal(rv.headers['X-Foo'], 'bar') def test_url_generation(self): app = flask.Flask(__name__) @@ -872,7 +872,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): # Test base case, a URL which results in a BuildError. with app.test_request_context(): - self.assertRaises(BuildError, flask.url_for, 'spam') + self.assert_raises(BuildError, flask.url_for, 'spam') # Verify the error is re-raised if not the current exception. try: @@ -883,7 +883,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): try: raise RuntimeError('Test case where BuildError is not current.') except RuntimeError: - self.assertRaises(BuildError, app.handle_url_build_error, error, 'spam', {}) + self.assert_raises(BuildError, app.handle_url_build_error, error, 'spam', {}) # Test a custom handler. def handler(error, endpoint, values): @@ -936,7 +936,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): def test_request_locals(self): self.assert_equal(repr(flask.g), '') - self.assertFalse(flask.g) + self.assert_false(flask.g) def test_test_app_proper_environ(self): app = flask.Flask(__name__) @@ -1205,9 +1205,9 @@ class BasicFunctionalityTestCase(FlaskTestCase): assert flask.url_for('123') == '/bar/123' c = app.test_client() - self.assertEqual(c.get('/foo/').data, b'foo') - self.assertEqual(c.get('/bar/').data, b'bar') - self.assertEqual(c.get('/bar/123').data, b'123') + self.assert_equal(c.get('/foo/').data, b'foo') + self.assert_equal(c.get('/bar/').data, b'bar') + self.assert_equal(c.get('/bar/123').data, b'123') def test_preserve_only_once(self): app = flask.Flask(__name__) @@ -1286,7 +1286,7 @@ class BasicFunctionalityTestCase(FlaskTestCase): self.assert_equal(sorted(flask.g), ['bar', 'foo']) -class SubdomainTestCase(FlaskTestCase): +class TestSubdomain(TestFlask): def test_basic_support(self): app = flask.Flask(__name__) @@ -1355,10 +1355,3 @@ class SubdomainTestCase(FlaskTestCase): self.assert_equal(rv.data, b'a') rv = app.test_client().open('/b/') self.assert_equal(rv.data, b'b') - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(BasicFunctionalityTestCase)) - suite.addTest(unittest.makeSuite(SubdomainTestCase)) - return suite diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index a5488a57..c8e85b4a 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -11,13 +11,13 @@ import flask import unittest -from tests import FlaskTestCase +from tests import TestFlask from flask._compat import text_type from werkzeug.http import parse_cache_control_header from jinja2 import TemplateNotFound -class BlueprintTestCase(FlaskTestCase): +class TestBlueprint(TestFlask): def test_blueprint_specific_error_handling(self): frontend = flask.Blueprint('frontend', __name__) @@ -303,11 +303,11 @@ class BlueprintTestCase(FlaskTestCase): return flask.request.endpoint c = app.test_client() - self.assertEqual(c.get('/').data, b'index') - self.assertEqual(c.get('/py/foo').data, b'bp.foo') - self.assertEqual(c.get('/py/bar').data, b'bp.bar') - self.assertEqual(c.get('/py/bar/123').data, b'bp.123') - self.assertEqual(c.get('/py/bar/foo').data, b'bp.bar_foo') + self.assert_equal(c.get('/').data, b'index') + self.assert_equal(c.get('/py/foo').data, b'bp.foo') + self.assert_equal(c.get('/py/bar').data, b'bp.bar') + self.assert_equal(c.get('/py/bar/123').data, b'bp.123') + self.assert_equal(c.get('/py/bar/foo').data, b'bp.bar_foo') def test_route_decorator_custom_endpoint_with_dots(self): bp = flask.Blueprint('bp', __name__) @@ -337,14 +337,14 @@ class BlueprintTestCase(FlaskTestCase): def foo_foo_foo(): pass - self.assertRaises( + self.assert_raises( AssertionError, lambda: bp.add_url_rule( '/bar/123', endpoint='bar.123', view_func=foo_foo_foo ) ) - self.assertRaises( + self.assert_raises( AssertionError, bp.route('/bar/123', endpoint='bar.123'), lambda: None @@ -354,7 +354,7 @@ class BlueprintTestCase(FlaskTestCase): app.register_blueprint(bp, url_prefix='/py') c = app.test_client() - self.assertEqual(c.get('/py/foo').data, b'bp.foo') + self.assert_equal(c.get('/py/foo').data, b'bp.foo') # The rule's didn't actually made it through rv = c.get('/py/bar') assert rv.status_code == 404 @@ -581,5 +581,5 @@ class BlueprintTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(BlueprintTestCase)) + suite.addTest(unittest.makeSuite(TestBlueprint)) return suite diff --git a/tests/test_config.py b/tests/test_config.py index 4f9e693f..99e2f45e 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -15,21 +15,21 @@ import flask import pkgutil import unittest from contextlib import contextmanager -from tests import FlaskTestCase +from tests import TestFlask from flask._compat import PY2 -# config keys used for the ConfigTestCase +# config keys used for the TestConfig TEST_KEY = 'foo' SECRET_KEY = 'devkey' -class ConfigTestCase(FlaskTestCase): +class TestConfig(TestFlask): def common_object_test(self, app): self.assert_equal(app.secret_key, 'devkey') self.assert_equal(app.config['TEST_KEY'], 'foo') - self.assert_not_in('ConfigTestCase', app.config) + self.assert_not_in('TestConfig', app.config) def test_config_from_file(self): app = flask.Flask(__name__) @@ -117,7 +117,7 @@ class ConfigTestCase(FlaskTestCase): self.assert_true(msg.endswith("missing.cfg'")) else: self.fail('expected IOError') - self.assertFalse(app.config.from_envvar('FOO_SETTINGS', silent=True)) + self.assert_false(app.config.from_envvar('FOO_SETTINGS', silent=True)) finally: os.environ = env @@ -207,7 +207,7 @@ def patch_pkgutil_get_loader(wrapper_class=LimitedLoaderMockWrapper): pkgutil.get_loader = old_get_loader -class InstanceTestCase(FlaskTestCase): +class TestInstance(TestFlask): def test_explicit_instance_paths(self): here = os.path.abspath(os.path.dirname(__file__)) @@ -379,6 +379,6 @@ class InstanceTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(ConfigTestCase)) - suite.addTest(unittest.makeSuite(InstanceTestCase)) + suite.addTest(unittest.makeSuite(TestConfig)) + suite.addTest(unittest.makeSuite(TestInstance)) return suite diff --git a/tests/test_deprecations.py b/tests/test_deprecations.py index 7353af5a..81fba63b 100644 --- a/tests/test_deprecations.py +++ b/tests/test_deprecations.py @@ -11,14 +11,14 @@ import flask import unittest -from tests import FlaskTestCase, catch_warnings +from tests import TestFlask, catch_warnings -class DeprecationsTestCase(FlaskTestCase): +class TestDeprecations(TestFlask): """not used currently""" def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(DeprecationsTestCase)) + suite.addTest(unittest.makeSuite(TestDeprecations)) return suite diff --git a/tests/test_examples.py b/tests/test_examples.py index c321a141..e4f66325 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -24,15 +24,15 @@ def suite(): setup_path() suite = unittest.TestSuite() try: - from minitwit_tests import MiniTwitTestCase + from minitwit_tests import TestMiniTwit except ImportError: pass else: - suite.addTest(unittest.makeSuite(MiniTwitTestCase)) + suite.addTest(unittest.makeSuite(TestMiniTwit)) try: - from flaskr_tests import FlaskrTestCase + from flaskr_tests import TestFlaskr except ImportError: pass else: - suite.addTest(unittest.makeSuite(FlaskrTestCase)) + suite.addTest(unittest.makeSuite(TestFlaskr)) return suite diff --git a/tests/test_ext.py b/tests/test_ext.py index 110657d8..e48563bf 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -15,10 +15,10 @@ try: from imp import reload as reload_module except ImportError: reload_module = reload -from tests import FlaskTestCase +from tests import TestFlask from flask._compat import PY2 -class ExtImportHookTestCase(FlaskTestCase): +class TestExtImportHook(TestFlask): def setup(self): # we clear this out for various reasons. The most important one is @@ -132,5 +132,5 @@ class ExtImportHookTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(ExtImportHookTestCase)) + suite.addTest(unittest.makeSuite(TestExtImportHook)) return suite diff --git a/tests/test_helpers.py b/tests/test_helpers.py index c923cae1..e5055fa6 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -13,7 +13,7 @@ import os import flask import unittest from logging import StreamHandler -from tests import FlaskTestCase, catch_warnings, catch_stderr +from tests import TestFlask, catch_warnings, catch_stderr from werkzeug.http import parse_cache_control_header, parse_options_header from flask._compat import StringIO, text_type @@ -27,7 +27,7 @@ def has_encoding(name): return False -class JSONTestCase(FlaskTestCase): +class TestJSON(TestFlask): def test_json_bad_requests(self): app = flask.Flask(__name__) @@ -148,7 +148,7 @@ class JSONTestCase(FlaskTestCase): rv = c.post('/', data=flask.json.dumps({ 'x': {'_foo': 42} }), content_type='application/json') - self.assertEqual(rv.data, b'"<42>"') + self.assert_equal(rv.data, b'"<42>"') def test_modified_url_encoding(self): class ModifiedRequest(flask.Request): @@ -240,7 +240,7 @@ class JSONTestCase(FlaskTestCase): except AssertionError: self.assert_equal(lines, sorted_by_str) -class SendfileTestCase(FlaskTestCase): +class TestSendfile(TestFlask): def test_send_file_regular(self): app = flask.Flask(__name__) @@ -422,7 +422,7 @@ class SendfileTestCase(FlaskTestCase): rv.close() -class LoggingTestCase(FlaskTestCase): +class TestLogging(TestFlask): def test_logger_cache(self): app = flask.Flask(__name__) @@ -450,7 +450,7 @@ class LoggingTestCase(FlaskTestCase): with catch_stderr() as err: c.get('/') out = err.getvalue() - self.assert_in('WARNING in helpers [', out) + self.assert_in('WARNING in test_helpers [', out) self.assert_in(os.path.basename(__file__.rsplit('.', 1)[0] + '.py'), out) self.assert_in('the standard library is dead', out) self.assert_in('this is a debug statement', out) @@ -572,7 +572,7 @@ class LoggingTestCase(FlaskTestCase): '/myview/create') -class NoImportsTestCase(FlaskTestCase): +class TestNoImports(TestFlask): """Test Flasks are created without import. Avoiding ``__import__`` helps create Flask instances where there are errors @@ -590,7 +590,7 @@ class NoImportsTestCase(FlaskTestCase): self.fail('Flask(import_name) is importing import_name.') -class StreamingTestCase(FlaskTestCase): +class TestStreaming(TestFlask): def test_streaming_with_context(self): app = flask.Flask(__name__) @@ -604,7 +604,7 @@ class StreamingTestCase(FlaskTestCase): return flask.Response(flask.stream_with_context(generate())) c = app.test_client() rv = c.get('/?name=World') - self.assertEqual(rv.data, b'Hello World!') + self.assert_equal(rv.data, b'Hello World!') def test_streaming_with_context_as_decorator(self): app = flask.Flask(__name__) @@ -619,7 +619,7 @@ class StreamingTestCase(FlaskTestCase): return flask.Response(generate()) c = app.test_client() rv = c.get('/?name=World') - self.assertEqual(rv.data, b'Hello World!') + self.assert_equal(rv.data, b'Hello World!') def test_streaming_with_context_and_custom_close(self): app = flask.Flask(__name__) @@ -645,16 +645,16 @@ class StreamingTestCase(FlaskTestCase): Wrapper(generate()))) c = app.test_client() rv = c.get('/?name=World') - self.assertEqual(rv.data, b'Hello World!') - self.assertEqual(called, [42]) + self.assert_equal(rv.data, b'Hello World!') + self.assert_equal(called, [42]) def suite(): suite = unittest.TestSuite() if flask.json_available: - suite.addTest(unittest.makeSuite(JSONTestCase)) - suite.addTest(unittest.makeSuite(SendfileTestCase)) - suite.addTest(unittest.makeSuite(LoggingTestCase)) - suite.addTest(unittest.makeSuite(NoImportsTestCase)) - suite.addTest(unittest.makeSuite(StreamingTestCase)) + suite.addTest(unittest.makeSuite(TestJSON)) + suite.addTest(unittest.makeSuite(TestSendfile)) + suite.addTest(unittest.makeSuite(TestLogging)) + suite.addTest(unittest.makeSuite(TestNoImports)) + suite.addTest(unittest.makeSuite(TestStreaming)) return suite diff --git a/tests/test_regression.py b/tests/test_regression.py index 8bdbbf6d..df766246 100644 --- a/tests/test_regression.py +++ b/tests/test_regression.py @@ -9,14 +9,15 @@ :license: BSD, see LICENSE for more details. """ +import pytest + import os import gc import sys import flask import threading -import unittest from werkzeug.exceptions import NotFound -from tests import FlaskTestCase +from tests import TestFlask _gc_lock = threading.Lock() @@ -51,13 +52,16 @@ class _NoLeakAsserter(object): gc.enable() -class MemoryTestCase(FlaskTestCase): +@pytest.mark.skipif(os.environ.get('RUN_FLASK_MEMORY_TESTS') != '1', + reason='Turned off due to envvar.') +class TestMemory(TestFlask): def assert_no_leak(self): return _NoLeakAsserter(self) def test_memory_consumption(self): app = flask.Flask(__name__) + @app.route('/') def index(): return flask.render_template('simple_template.html', whiskey=42) @@ -84,33 +88,28 @@ class MemoryTestCase(FlaskTestCase): safe_join('/foo', '..') -class ExceptionTestCase(FlaskTestCase): +class TestException(TestFlask): def test_aborting(self): class Foo(Exception): whatever = 42 app = flask.Flask(__name__) app.testing = True + @app.errorhandler(Foo) def handle_foo(e): return str(e.whatever) + @app.route('/') def index(): raise flask.abort(flask.redirect(flask.url_for('test'))) + @app.route('/test') def test(): raise Foo() with app.test_client() as c: rv = c.get('/') - self.assertEqual(rv.headers['Location'], 'http://localhost/test') + self.assert_equal(rv.headers['Location'], 'http://localhost/test') rv = c.get('/test') - self.assertEqual(rv.data, b'42') - - -def suite(): - suite = unittest.TestSuite() - if os.environ.get('RUN_FLASK_MEMORY_TESTS') == '1': - suite.addTest(unittest.makeSuite(MemoryTestCase)) - suite.addTest(unittest.makeSuite(ExceptionTestCase)) - return suite + self.assert_equal(rv.data, b'42') diff --git a/tests/test_reqctx.py b/tests/test_reqctx.py index 4ea04098..6787d90a 100644 --- a/tests/test_reqctx.py +++ b/tests/test_reqctx.py @@ -15,10 +15,10 @@ try: from greenlet import greenlet except ImportError: greenlet = None -from tests import FlaskTestCase +from tests import TestFlask -class RequestContextTestCase(FlaskTestCase): +class TestRequestContext(TestFlask): def test_teardown_on_pop(self): buffer = [] @@ -197,5 +197,5 @@ class RequestContextTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(RequestContextTestCase)) + suite.addTest(unittest.makeSuite(TestRequestContext)) return suite diff --git a/tests/test_signals.py b/tests/test_signals.py index d05b5b27..db3287e5 100644 --- a/tests/test_signals.py +++ b/tests/test_signals.py @@ -11,10 +11,10 @@ import flask import unittest -from tests import FlaskTestCase +from tests import TestFlask -class SignalsTestCase(FlaskTestCase): +class TestSignals(TestFlask): def test_template_rendered(self): app = flask.Flask(__name__) @@ -149,5 +149,5 @@ class SignalsTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() if flask.signals_available: - suite.addTest(unittest.makeSuite(SignalsTestCase)) + suite.addTest(unittest.makeSuite(TestSignals)) return suite diff --git a/tests/test_subclassing.py b/tests/test_subclassing.py index 41e587e7..b5c85dfd 100644 --- a/tests/test_subclassing.py +++ b/tests/test_subclassing.py @@ -12,11 +12,11 @@ import flask import unittest from logging import StreamHandler -from tests import FlaskTestCase +from tests import TestFlask from flask._compat import StringIO -class FlaskSubclassingTestCase(FlaskTestCase): +class TestFlaskSubclassing(TestFlask): def test_suppressed_exception_logging(self): class SuppressedFlask(flask.Flask): @@ -42,5 +42,5 @@ class FlaskSubclassingTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(FlaskSubclassingTestCase)) + suite.addTest(unittest.makeSuite(TestFlaskSubclassing)) return suite diff --git a/tests/test_templating.py b/tests/test_templating.py index 5ce67d97..9727d21d 100644 --- a/tests/test_templating.py +++ b/tests/test_templating.py @@ -14,10 +14,10 @@ import unittest import logging from jinja2 import TemplateNotFound -from tests import FlaskTestCase +from tests import TestFlask -class TemplatingTestCase(FlaskTestCase): +class TestTemplating(TestFlask): def test_context_processing(self): app = flask.Flask(__name__) @@ -348,5 +348,5 @@ class TemplatingTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TemplatingTestCase)) + suite.addTest(unittest.makeSuite(TestTemplating)) return suite diff --git a/tests/test_testing.py b/tests/test_testing.py index 3a51c59f..257cf7d0 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -8,14 +8,15 @@ :copyright: (c) 2014 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ +import pytest import flask import unittest -from tests import FlaskTestCase +from tests import TestFlask from flask._compat import text_type -class TestToolsTestCase(FlaskTestCase): +class TestTestTools(TestFlask): def test_environ_defaults_from_config(self): app = flask.Flask(__name__) @@ -212,46 +213,45 @@ class TestToolsTestCase(FlaskTestCase): self.assert_true('vodka' in flask.request.args) -class SubdomainTestCase(FlaskTestCase): +class TestSubdomain(TestFlask): - def setUp(self): - self.app = flask.Flask(__name__) - self.app.config['SERVER_NAME'] = 'example.com' - self.client = self.app.test_client() + @pytest.fixture + def app(self, request): + app = flask.Flask(__name__) + app.config['SERVER_NAME'] = 'example.com' - self._ctx = self.app.test_request_context() - self._ctx.push() + ctx = app.test_request_context() + ctx.push() - def tearDown(self): - if self._ctx is not None: - self._ctx.pop() + def teardown(): + if ctx is not None: + ctx.pop() + request.addfinalizer(teardown) + return app - def test_subdomain(self): - @self.app.route('/', subdomain='') + @pytest.fixture + def client(self, app): + return app.test_client() + + def test_subdomain(self, app, client): + @app.route('/', subdomain='') def view(company_id): return company_id url = flask.url_for('view', company_id='xxx') - response = self.client.get(url) + response = client.get(url) self.assert_equal(200, response.status_code) self.assert_equal(b'xxx', response.data) - def test_nosubdomain(self): - @self.app.route('/') + def test_nosubdomain(self, app, client): + @app.route('/') def view(company_id): return company_id url = flask.url_for('view', company_id='xxx') - response = self.client.get(url) + response = client.get(url) self.assert_equal(200, response.status_code) self.assert_equal(b'xxx', response.data) - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestToolsTestCase)) - suite.addTest(unittest.makeSuite(SubdomainTestCase)) - return suite diff --git a/tests/test_views.py b/tests/test_views.py index f98f920b..a98bc2f0 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -12,10 +12,10 @@ import flask import flask.views import unittest -from tests import FlaskTestCase +from tests import TestFlask from werkzeug.http import parse_set_header -class ViewTestCase(FlaskTestCase): +class TestView(TestFlask): def common_test(self, app): c = app.test_client() @@ -165,5 +165,5 @@ class ViewTestCase(FlaskTestCase): def suite(): suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(ViewTestCase)) + suite.addTest(unittest.makeSuite(TestView)) return suite From b93ab41ed12c3dd0c37fb7a85f1aa93966b46d77 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Sun, 31 Aug 2014 23:59:43 +0200 Subject: [PATCH 05/33] Remove testsuite package from setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a66118f1..12c656d1 100644 --- a/setup.py +++ b/setup.py @@ -92,7 +92,7 @@ setup( description='A microframework based on Werkzeug, Jinja2 ' 'and good intentions', long_description=__doc__, - packages=['flask', 'flask.ext', 'flask.testsuite'], + packages=['flask', 'flask.ext'], include_package_data=True, zip_safe=False, platforms='any', From ec863cef5bb3811803337738c93c65541848a403 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 1 Sep 2014 00:00:20 +0200 Subject: [PATCH 06/33] Update tox --- tox.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 24155a9a..46792253 100644 --- a/tox.ini +++ b/tox.ini @@ -2,8 +2,10 @@ envlist = docs, py26, py27, pypy, py33, py34 [testenv] -deps = blinker -commands = python run-tests.py [] +deps= + blinker + pytest +commands = py.test [] [testenv:docs] From 8d97d7143079dd862564a1e119ad44817ba176d6 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 1 Sep 2014 00:30:27 +0200 Subject: [PATCH 07/33] Metadata change --- .travis-devel-requirements.txt | 6 ----- .travis-lowest-requirements.txt | 6 ----- .travis-release-requirements.txt | 2 -- .travis.yml | 8 +++--- Makefile | 2 +- .../{flaskext_test.py => flaskext_tester.py} | 0 setup.cfg | 3 --- tox.ini | 25 +++++++++++++++---- 8 files changed, 26 insertions(+), 26 deletions(-) delete mode 100644 .travis-devel-requirements.txt delete mode 100644 .travis-lowest-requirements.txt delete mode 100644 .travis-release-requirements.txt rename scripts/{flaskext_test.py => flaskext_tester.py} (100%) diff --git a/.travis-devel-requirements.txt b/.travis-devel-requirements.txt deleted file mode 100644 index 18ee00ec..00000000 --- a/.travis-devel-requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -git+git://github.com/mitsuhiko/werkzeug.git#egg=Werkzeug -git+git://github.com/mitsuhiko/jinja2.git#egg=Jinja2 -git+git://github.com/mitsuhiko/itsdangerous.git#egg=itsdangerous - -# extra dependencies -git+git://github.com/jek/blinker.git#egg=blinker diff --git a/.travis-lowest-requirements.txt b/.travis-lowest-requirements.txt deleted file mode 100644 index 5066d698..00000000 --- a/.travis-lowest-requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -Werkzeug==0.7 -Jinja2==2.4 -itsdangerous==0.21 - -# extra dependencies -blinker==1.0 diff --git a/.travis-release-requirements.txt b/.travis-release-requirements.txt deleted file mode 100644 index f2f097cb..00000000 --- a/.travis-release-requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -# extra dependencies -blinker diff --git a/.travis.yml b/.travis.yml index 92f070c2..1fa286a6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ python: - "2.7" - "pypy" - "3.3" + - "3.4" env: - REQUIREMENTS=lowest @@ -18,10 +19,11 @@ matrix: env: REQUIREMENTS=lowest install: - - pip install -r .travis-$REQUIREMENTS-requirements.txt - - pip install --editable . + - pip install hg+https://bitbucket.org/hpk42/tox -script: make test +script: + - tox -e \ + $(echo py$TRAVIS_PYTHON_VERSION | tr -d . | sed -e 's/pypypy/pypy/')-$REQUIREMENTS branches: except: diff --git a/Makefile b/Makefile index 98e74135..e1835e8c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all: clean-pyc test test: - python run-tests.py + py.test tox-test: tox diff --git a/scripts/flaskext_test.py b/scripts/flaskext_tester.py similarity index 100% rename from scripts/flaskext_test.py rename to scripts/flaskext_tester.py diff --git a/setup.cfg b/setup.cfg index c3b4abda..dbd1f97a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[pytest] -norecursedirs= scripts docs - [aliases] release = egg_info -RDb '' diff --git a/tox.ini b/tox.ini index 46792253..da76c277 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,27 @@ [tox] -envlist = docs, py26, py27, pypy, py33, py34 +envlist = + docs + {py26,py27,pypy,py33,py34}-{lowest,release,devel} [testenv] -deps= - blinker - pytest -commands = py.test [] +commands = + py.test [] +deps= + pytest + + lowest: Werkzeug==0.7 + lowest: Jinja==2.4 + lowest: itsdangerous==0.21 + lowest: blinker==1.0 + release: blinker + devel: git+git://github.com/mitsuhiko/werkzeug.git + devel: git+git://github.com/mitsuhiko/jinja2.git + devel: git+git://github.com/mitsuhiko/itsdangerous.git + devel: git+git://github.com/jek/blinker.git + +# extra dependencies +git+git://github.com/jek/blinker.git#egg=blinker [testenv:docs] deps = sphinx From df711eac90223db990eae05a60ee1f6b403443e1 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 1 Sep 2014 16:33:28 +0200 Subject: [PATCH 08/33] Some fixes --- .travis.yml | 3 +++ tests/test_config.py | 16 ++++++++-------- tox.ini | 6 ++---- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1fa286a6..9a1a8a8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,9 @@ matrix: # Python 3 support currently does not work with lowest requirements - python: "3.3" env: REQUIREMENTS=lowest + - python: "3.4" + env: REQUIREMENTS=lowest + install: - pip install hg+https://bitbucket.org/hpk42/tox diff --git a/tests/test_config.py b/tests/test_config.py index 99e2f45e..89f71998 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -344,23 +344,23 @@ class TestInstance(TestFlask): if 'site_package' in sys.modules: del sys.modules['site_package'] - def test_egg_installed_paths(self): + def test_egg_installed_paths(self, monkeypatch): here = os.path.abspath(os.path.dirname(__file__)) expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', 'site-packages') + monkeypatch.setattr(sys, 'prefix', expected_prefix) + + site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', + 'site-packages') egg_path = os.path.join(site_packages, 'SiteEgg.egg') - sys.path.append(site_packages) - sys.path.append(egg_path) + monkeypatch.syspath_prepend(egg_path) + monkeypatch.syspath_prepend(site_packages) + try: import site_egg # in SiteEgg.egg self.assert_equal(site_egg.app.instance_path, os.path.join(expected_prefix, 'var', 'site_egg-instance')) finally: - sys.prefix = real_prefix - sys.path.remove(site_packages) - sys.path.remove(egg_path) if 'site_egg' in sys.modules: del sys.modules['site_egg'] diff --git a/tox.ini b/tox.ini index da76c277..340d6f52 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,5 @@ [tox] -envlist = - docs - {py26,py27,pypy,py33,py34}-{lowest,release,devel} +envlist = {py26,py27,pypy,py33,py34}-{lowest,release,devel} [testenv] commands = @@ -11,7 +9,7 @@ deps= pytest lowest: Werkzeug==0.7 - lowest: Jinja==2.4 + lowest: Jinja2==2.4 lowest: itsdangerous==0.21 lowest: blinker==1.0 release: blinker From a497b10d4fe345c524ad7df24a2c44b066a10abe Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 1 Sep 2014 16:49:06 +0200 Subject: [PATCH 09/33] Don't test old Werkzeug against py3 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 340d6f52..687b5c2b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = {py26,py27,pypy,py33,py34}-{lowest,release,devel} +envlist = {py26,py27,pypy}-{lowest,release,devel}, {py33,py34}-{release,devel} [testenv] commands = From ba82bac3d80400b5520cac7d0a8915414325bcf6 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 1 Sep 2014 18:03:16 +0200 Subject: [PATCH 10/33] Rework test_config --- tests/test_config.py | 327 +++++++++++++++++++++---------------------- 1 file changed, 160 insertions(+), 167 deletions(-) diff --git a/tests/test_config.py b/tests/test_config.py index 89f71998..621df150 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -9,11 +9,14 @@ :license: BSD, see LICENSE for more details. """ +import pytest + import os import sys import flask import pkgutil import unittest +import textwrap from contextlib import contextmanager from tests import TestFlask from flask._compat import PY2 @@ -178,188 +181,185 @@ class TestConfig(TestFlask): self.assert_equal('bar stuff 2', bar_options['STUFF_2']) -class LimitedLoaderMockWrapper(object): - def __init__(self, loader): - self.loader = loader - - def __getattr__(self, name): - if name in ('archive', 'get_filename'): - msg = 'Mocking a loader which does not have `%s.`' % name - raise AttributeError(msg) - return getattr(self.loader, name) - - -@contextmanager -def patch_pkgutil_get_loader(wrapper_class=LimitedLoaderMockWrapper): +@pytest.fixture(params=(True, False)) +def limit_loader(request, monkeypatch): """Patch pkgutil.get_loader to give loader without get_filename or archive. This provides for tests where a system has custom loaders, e.g. Google App Engine's HardenedModulesHook, which have neither the `get_filename` method nor the `archive` attribute. + + This fixture will run the testcase twice, once with and once without the + limitation/mock. """ + if not request.param: + return + + class LimitedLoader(object): + def __init__(self, loader): + self.loader = loader + + def __getattr__(self, name): + if name in ('archive', 'get_filename'): + msg = 'Mocking a loader which does not have `%s.`' % name + raise AttributeError(msg) + return getattr(self.loader, name) + old_get_loader = pkgutil.get_loader def get_loader(*args, **kwargs): - return wrapper_class(old_get_loader(*args, **kwargs)) - try: - pkgutil.get_loader = get_loader - yield - finally: - pkgutil.get_loader = old_get_loader - + return LimitedLoader(old_get_loader(*args, **kwargs)) + monkeypatch.setattr(pkgutil, 'get_loader', get_loader) class TestInstance(TestFlask): + @pytest.fixture + def apps_tmpdir(self, tmpdir, monkeypatch): + '''Test folder for all instance tests.''' + rv = tmpdir.mkdir('test_apps') + monkeypatch.syspath_prepend(str(rv)) + return rv - def test_explicit_instance_paths(self): - here = os.path.abspath(os.path.dirname(__file__)) - try: + @pytest.fixture + def apps_tmpdir_prefix(self, apps_tmpdir, monkeypatch): + monkeypatch.setattr(sys, 'prefix', str(apps_tmpdir)) + return apps_tmpdir + + @pytest.fixture + def site_packages(self, apps_tmpdir, monkeypatch): + '''Create a fake site-packages''' + rv = apps_tmpdir \ + .mkdir('lib')\ + .mkdir('python{x[0]}.{x[1]}'.format(x=sys.version_info))\ + .mkdir('site-packages') + monkeypatch.syspath_prepend(str(rv)) + return rv + + @pytest.fixture + def install_egg(self, apps_tmpdir, monkeypatch): + '''Generate egg from package name inside base and put the egg into + sys.path''' + def inner(name, base=apps_tmpdir): + if not isinstance(name, str): + raise ValueError(name) + base.join(name).ensure_dir() + base.join(name).join('__init__.py').ensure() + + egg_setup = base.join('setup.py') + egg_setup.write(textwrap.dedent(""" + from setuptools import setup + setup(name='{0}', + version='1.0', + packages=['site_egg'], + zip_safe=True) + """.format(name))) + + import subprocess + subprocess.check_call( + [sys.executable, 'setup.py', 'bdist_egg'], + cwd=str(apps_tmpdir) + ) + egg_path, = apps_tmpdir.join('dist/').listdir() + monkeypatch.syspath_prepend(str(egg_path)) + return egg_path + return inner + + @pytest.fixture + def purge_module(self, request): + def inner(name): + request.addfinalizer(lambda: sys.modules.pop(name, None)) + return inner + + def test_explicit_instance_paths(self, apps_tmpdir): + with pytest.raises(ValueError) as excinfo: flask.Flask(__name__, instance_path='instance') - except ValueError as e: - self.assert_in('must be absolute', str(e)) - else: - self.fail('Expected value error') + assert 'must be absolute' in str(excinfo.value) - app = flask.Flask(__name__, instance_path=here) - self.assert_equal(app.instance_path, here) + app = flask.Flask(__name__, instance_path=str(apps_tmpdir)) + self.assert_equal(app.instance_path, str(apps_tmpdir)) + + def test_main_module_paths(self, apps_tmpdir, purge_module): + app = apps_tmpdir.join('main_app.py') + app.write('import flask\n\napp = flask.Flask("__main__")') + purge_module('main_app') - def test_main_module_paths(self): - # Test an app with '__main__' as the import name, uses cwd. from main_app import app here = os.path.abspath(os.getcwd()) - self.assert_equal(app.instance_path, os.path.join(here, 'instance')) - if 'main_app' in sys.modules: - del sys.modules['main_app'] + assert app.instance_path == os.path.join(here, 'instance') + + def test_uninstalled_module_paths(self, apps_tmpdir, purge_module): + app = apps_tmpdir.join('config_module_app.py').write( + 'import os\n' + 'import flask\n' + 'here = os.path.abspath(os.path.dirname(__file__))\n' + 'app = flask.Flask(__name__)\n' + ) + purge_module('config_module_app') - def test_uninstalled_module_paths(self): from config_module_app import app - here = os.path.abspath(os.path.dirname(__file__)) - self.assert_equal(app.instance_path, os.path.join(here, 'test_apps', 'instance')) + assert app.instance_path == str(apps_tmpdir.join('instance')) + + def test_uninstalled_package_paths(self, apps_tmpdir, purge_module): + app = apps_tmpdir.mkdir('config_package_app') + init = app.join('__init__.py') + init.write( + 'import os\n' + 'import flask\n' + 'here = os.path.abspath(os.path.dirname(__file__))\n' + 'app = flask.Flask(__name__)\n' + ) + purge_module('config_package_app') - def test_uninstalled_package_paths(self): from config_package_app import app - here = os.path.abspath(os.path.dirname(__file__)) - self.assert_equal(app.instance_path, os.path.join(here, 'test_apps', 'instance')) + assert app.instance_path == str(apps_tmpdir.join('instance')) - def test_installed_module_paths(self): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', 'site-packages') - sys.path.append(site_packages) + def test_installed_module_paths(self, apps_tmpdir, apps_tmpdir_prefix, + purge_module, site_packages, limit_loader): + site_packages.join('site_app.py').write( + 'import flask\n' + 'app = flask.Flask(__name__)\n' + ) + purge_module('site_app') + + from site_app import app + assert app.instance_path == \ + apps_tmpdir.join('var').join('site_app-instance') + + def test_installed_package_paths(self, limit_loader, apps_tmpdir, + apps_tmpdir_prefix, purge_module, + monkeypatch): + installed_path = apps_tmpdir.mkdir('path') + monkeypatch.syspath_prepend(installed_path) + + app = installed_path.mkdir('installed_package') + init = app.join('__init__.py') + init.write('import flask\napp = flask.Flask(__name__)') + purge_module('installed_package') + + from installed_package import app + assert app.instance_path == \ + apps_tmpdir.join('var').join('installed_package-instance') + + def test_prefix_package_paths(self, limit_loader, apps_tmpdir, + apps_tmpdir_prefix, purge_module, + site_packages): + app = site_packages.mkdir('site_package') + init = app.join('__init__.py') + init.write('import flask\napp = flask.Flask(__name__)') + purge_module('site_package') + + import site_package + assert site_package.app.instance_path == \ + apps_tmpdir.join('var').join('site_package-instance') + + def test_egg_installed_paths(self, install_egg, apps_tmpdir, + apps_tmpdir_prefix): + apps_tmpdir.mkdir('site_egg').join('__init__.py').write( + 'import flask\n\napp = flask.Flask(__name__)' + ) + install_egg('site_egg') try: - import site_app - self.assert_equal(site_app.app.instance_path, - os.path.join(expected_prefix, 'var', - 'site_app-instance')) - finally: - sys.prefix = real_prefix - sys.path.remove(site_packages) - if 'site_app' in sys.modules: - del sys.modules['site_app'] - - def test_installed_module_paths_with_limited_loader(self): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', 'site-packages') - sys.path.append(site_packages) - with patch_pkgutil_get_loader(): - try: - import site_app - self.assert_equal(site_app.app.instance_path, - os.path.join(expected_prefix, 'var', - 'site_app-instance')) - finally: - sys.prefix = real_prefix - sys.path.remove(site_packages) - if 'site_app' in sys.modules: - del sys.modules['site_app'] - - def test_installed_package_paths(self): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - installed_path = os.path.join(expected_prefix, 'path') - sys.path.append(installed_path) - try: - import installed_package - self.assert_equal(installed_package.app.instance_path, - os.path.join(expected_prefix, 'var', - 'installed_package-instance')) - finally: - sys.prefix = real_prefix - sys.path.remove(installed_path) - if 'installed_package' in sys.modules: - del sys.modules['installed_package'] - - def test_installed_package_paths_with_limited_loader(self): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - installed_path = os.path.join(expected_prefix, 'path') - sys.path.append(installed_path) - with patch_pkgutil_get_loader(): - try: - import installed_package - self.assert_equal(installed_package.app.instance_path, - os.path.join(expected_prefix, 'var', - 'installed_package-instance')) - finally: - sys.prefix = real_prefix - sys.path.remove(installed_path) - if 'installed_package' in sys.modules: - del sys.modules['installed_package'] - - def test_prefix_package_paths(self): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', 'site-packages') - sys.path.append(site_packages) - try: - import site_package - self.assert_equal(site_package.app.instance_path, - os.path.join(expected_prefix, 'var', - 'site_package-instance')) - finally: - sys.prefix = real_prefix - sys.path.remove(site_packages) - if 'site_package' in sys.modules: - del sys.modules['site_package'] - - def test_prefix_package_paths_with_limited_loader(self): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - real_prefix, sys.prefix = sys.prefix, expected_prefix - site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', 'site-packages') - sys.path.append(site_packages) - with patch_pkgutil_get_loader(): - try: - import site_package - self.assert_equal(site_package.app.instance_path, - os.path.join(expected_prefix, 'var', - 'site_package-instance')) - finally: - sys.prefix = real_prefix - sys.path.remove(site_packages) - if 'site_package' in sys.modules: - del sys.modules['site_package'] - - def test_egg_installed_paths(self, monkeypatch): - here = os.path.abspath(os.path.dirname(__file__)) - expected_prefix = os.path.join(here, 'test_apps') - monkeypatch.setattr(sys, 'prefix', expected_prefix) - - site_packages = os.path.join(expected_prefix, 'lib', 'python2.5', - 'site-packages') - egg_path = os.path.join(site_packages, 'SiteEgg.egg') - monkeypatch.syspath_prepend(egg_path) - monkeypatch.syspath_prepend(site_packages) - - try: - import site_egg # in SiteEgg.egg - self.assert_equal(site_egg.app.instance_path, - os.path.join(expected_prefix, 'var', - 'site_egg-instance')) + import site_egg + assert site_egg.app.instance_path == \ + str(apps_tmpdir.join('var/').join('site_egg-instance')) finally: if 'site_egg' in sys.modules: del sys.modules['site_egg'] @@ -375,10 +375,3 @@ class TestInstance(TestFlask): flask.Flask(__name__) finally: sys.meta_path.pop() - - -def suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestConfig)) - suite.addTest(unittest.makeSuite(TestInstance)) - return suite From b1c0951ad690a83e49bfd005853a7b09cdb44cb0 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Mon, 1 Sep 2014 19:06:32 +0200 Subject: [PATCH 11/33] Move fixtures --- tests/conftest.py | 105 +++++++++++++++++++++++++++++++++++++++++++ tests/test_config.py | 86 ----------------------------------- 2 files changed, 105 insertions(+), 86 deletions(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..ed11084b --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +""" + tests.conftest + ~~~~~~~~~~~~~~ + + :copyright: (c) 2014 by the Flask Team, see AUTHORS for more details. + :license: BSD, see LICENSE for more details. +""" +import pkgutil +import pytest +import sys +import textwrap + + +@pytest.fixture(params=(True, False)) +def limit_loader(request, monkeypatch): + """Patch pkgutil.get_loader to give loader without get_filename or archive. + + This provides for tests where a system has custom loaders, e.g. Google App + Engine's HardenedModulesHook, which have neither the `get_filename` method + nor the `archive` attribute. + + This fixture will run the testcase twice, once with and once without the + limitation/mock. + """ + if not request.param: + return + + class LimitedLoader(object): + def __init__(self, loader): + self.loader = loader + + def __getattr__(self, name): + if name in ('archive', 'get_filename'): + msg = 'Mocking a loader which does not have `%s.`' % name + raise AttributeError(msg) + return getattr(self.loader, name) + + old_get_loader = pkgutil.get_loader + + def get_loader(*args, **kwargs): + return LimitedLoader(old_get_loader(*args, **kwargs)) + monkeypatch.setattr(pkgutil, 'get_loader', get_loader) + + +@pytest.fixture +def apps_tmpdir(tmpdir, monkeypatch): + '''Test folder for all instance tests.''' + rv = tmpdir.mkdir('test_apps') + monkeypatch.syspath_prepend(str(rv)) + return rv + + +@pytest.fixture +def apps_tmpdir_prefix(apps_tmpdir, monkeypatch): + monkeypatch.setattr(sys, 'prefix', str(apps_tmpdir)) + return apps_tmpdir + + +@pytest.fixture +def site_packages(apps_tmpdir, monkeypatch): + '''Create a fake site-packages''' + rv = apps_tmpdir \ + .mkdir('lib')\ + .mkdir('python{x[0]}.{x[1]}'.format(x=sys.version_info))\ + .mkdir('site-packages') + monkeypatch.syspath_prepend(str(rv)) + return rv + + +@pytest.fixture +def install_egg(apps_tmpdir, monkeypatch): + '''Generate egg from package name inside base and put the egg into + sys.path''' + def inner(name, base=apps_tmpdir): + if not isinstance(name, str): + raise ValueError(name) + base.join(name).ensure_dir() + base.join(name).join('__init__.py').ensure() + + egg_setup = base.join('setup.py') + egg_setup.write(textwrap.dedent(""" + from setuptools import setup + setup(name='{0}', + version='1.0', + packages=['site_egg'], + zip_safe=True) + """.format(name))) + + import subprocess + subprocess.check_call( + [sys.executable, 'setup.py', 'bdist_egg'], + cwd=str(apps_tmpdir) + ) + egg_path, = apps_tmpdir.join('dist/').listdir() + monkeypatch.syspath_prepend(str(egg_path)) + return egg_path + return inner + + +@pytest.fixture +def purge_module(request): + def inner(name): + request.addfinalizer(lambda: sys.modules.pop(name, None)) + return inner diff --git a/tests/test_config.py b/tests/test_config.py index 621df150..a0e5fb53 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -181,93 +181,7 @@ class TestConfig(TestFlask): self.assert_equal('bar stuff 2', bar_options['STUFF_2']) -@pytest.fixture(params=(True, False)) -def limit_loader(request, monkeypatch): - """Patch pkgutil.get_loader to give loader without get_filename or archive. - - This provides for tests where a system has custom loaders, e.g. Google App - Engine's HardenedModulesHook, which have neither the `get_filename` method - nor the `archive` attribute. - - This fixture will run the testcase twice, once with and once without the - limitation/mock. - """ - if not request.param: - return - - class LimitedLoader(object): - def __init__(self, loader): - self.loader = loader - - def __getattr__(self, name): - if name in ('archive', 'get_filename'): - msg = 'Mocking a loader which does not have `%s.`' % name - raise AttributeError(msg) - return getattr(self.loader, name) - - old_get_loader = pkgutil.get_loader - def get_loader(*args, **kwargs): - return LimitedLoader(old_get_loader(*args, **kwargs)) - monkeypatch.setattr(pkgutil, 'get_loader', get_loader) - class TestInstance(TestFlask): - @pytest.fixture - def apps_tmpdir(self, tmpdir, monkeypatch): - '''Test folder for all instance tests.''' - rv = tmpdir.mkdir('test_apps') - monkeypatch.syspath_prepend(str(rv)) - return rv - - @pytest.fixture - def apps_tmpdir_prefix(self, apps_tmpdir, monkeypatch): - monkeypatch.setattr(sys, 'prefix', str(apps_tmpdir)) - return apps_tmpdir - - @pytest.fixture - def site_packages(self, apps_tmpdir, monkeypatch): - '''Create a fake site-packages''' - rv = apps_tmpdir \ - .mkdir('lib')\ - .mkdir('python{x[0]}.{x[1]}'.format(x=sys.version_info))\ - .mkdir('site-packages') - monkeypatch.syspath_prepend(str(rv)) - return rv - - @pytest.fixture - def install_egg(self, apps_tmpdir, monkeypatch): - '''Generate egg from package name inside base and put the egg into - sys.path''' - def inner(name, base=apps_tmpdir): - if not isinstance(name, str): - raise ValueError(name) - base.join(name).ensure_dir() - base.join(name).join('__init__.py').ensure() - - egg_setup = base.join('setup.py') - egg_setup.write(textwrap.dedent(""" - from setuptools import setup - setup(name='{0}', - version='1.0', - packages=['site_egg'], - zip_safe=True) - """.format(name))) - - import subprocess - subprocess.check_call( - [sys.executable, 'setup.py', 'bdist_egg'], - cwd=str(apps_tmpdir) - ) - egg_path, = apps_tmpdir.join('dist/').listdir() - monkeypatch.syspath_prepend(str(egg_path)) - return egg_path - return inner - - @pytest.fixture - def purge_module(self, request): - def inner(name): - request.addfinalizer(lambda: sys.modules.pop(name, None)) - return inner - def test_explicit_instance_paths(self, apps_tmpdir): with pytest.raises(ValueError) as excinfo: flask.Flask(__name__, instance_path='instance') From dd6b2574c9d40c4777da71d576f6e5eea1712404 Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Tue, 2 Sep 2014 05:10:16 +0200 Subject: [PATCH 12/33] Rework test_signals --- tests/test_signals.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tests/test_signals.py b/tests/test_signals.py index db3287e5..fbbfda61 100644 --- a/tests/test_signals.py +++ b/tests/test_signals.py @@ -9,11 +9,22 @@ :license: BSD, see LICENSE for more details. """ +import pytest + +try: + import blinker +except ImportError: + blinker = None + import flask -import unittest from tests import TestFlask +pytestmark = pytest.mark.skipif( + blinker is None, + reason='Signals require the blinker library.' +) + class TestSignals(TestFlask): def test_template_rendered(self): @@ -24,6 +35,7 @@ class TestSignals(TestFlask): return flask.render_template('simple_template.html', whiskey=42) recorded = [] + def record(sender, template, context): recorded.append((template, context)) @@ -71,8 +83,8 @@ class TestSignals(TestFlask): self.assert_equal(rv.data, b'stuff') self.assert_equal(calls, ['before-signal', 'before-handler', - 'handler', 'after-handler', - 'after-signal']) + 'handler', 'after-handler', + 'after-signal']) finally: flask.request_started.disconnect(before_request_signal, app) flask.request_finished.disconnect(after_request_signal, app) @@ -99,8 +111,10 @@ class TestSignals(TestFlask): def test_appcontext_signals(self): app = flask.Flask(__name__) recorded = [] + def record_push(sender, **kwargs): recorded.append('push') + def record_pop(sender, **kwargs): recorded.append('pop') @@ -130,6 +144,7 @@ class TestSignals(TestFlask): return flask.redirect('/other') recorded = [] + def record(sender, message, category): recorded.append((message, category)) @@ -144,10 +159,3 @@ class TestSignals(TestFlask): self.assert_equal(category, 'notice') finally: flask.message_flashed.disconnect(record, app) - - -def suite(): - suite = unittest.TestSuite() - if flask.signals_available: - suite.addTest(unittest.makeSuite(TestSignals)) - return suite From 5da2c00419d09ce2d3488263036ffd14563fb05a Mon Sep 17 00:00:00 2001 From: Markus Unterwaditzer Date: Tue, 2 Sep 2014 05:26:52 +0200 Subject: [PATCH 13/33] Rewrite assertion methods --- tests/__init__.py | 34 +-- tests/test_appctx.py | 33 +-- tests/test_basic.py | 505 +++++++++++++++++++------------------- tests/test_blueprints.py | 150 +++++------ tests/test_config.py | 66 ++--- tests/test_ext.py | 53 ++-- tests/test_helpers.py | 194 +++++++-------- tests/test_regression.py | 10 +- tests/test_reqctx.py | 95 ++++--- tests/test_signals.py | 33 ++- tests/test_subclassing.py | 6 +- tests/test_templating.py | 128 +++++----- tests/test_testing.py | 74 +++--- tests/test_views.py | 32 +-- 14 files changed, 694 insertions(+), 719 deletions(-) diff --git a/tests/__init__.py b/tests/__init__.py index 9c349854..30024d10 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -78,9 +78,9 @@ def emits_module_deprecation_warning(f): def new_f(self, *args, **kwargs): with catch_warnings() as log: f(self, *args, **kwargs) - self.assert_true(log, 'expected deprecation warning') + assert log, 'expected deprecation warning' for entry in log: - self.assert_in('Modules are deprecated', str(entry['message'])) + assert 'Modules are deprecated' in str(entry['message']) return update_wrapper(new_f, f) @@ -107,7 +107,7 @@ class TestFlask(object): leaks = [] while flask._request_ctx_stack.top is not None: leaks.append(flask._request_ctx_stack.pop()) - self.assert_equal(leaks, []) + assert leaks == [] def setup_method(self, method): self.setup() @@ -120,31 +120,3 @@ class TestFlask(object): def teardown(self): pass - - def assert_equal(self, x, y): - assert x == y - - def assert_raises(self, exc_type, callable=None, *args, **kwargs): - if callable: - return pytest.raises(exc_type, callable, *args, **kwargs) - else: - return pytest.raises(exc_type) - - def assert_true(self, x, msg=None): - assert x - assert_ = assert_true - - def assert_false(self, x, msg=None): - assert not x - - def assert_in(self, x, y): - assert x in y - - def assert_not_in(self, x, y): - assert x not in y - - def assert_isinstance(self, obj, cls): - assert isinstance(obj, cls) - - def fail(self, msg): - raise AssertionError(msg) diff --git a/tests/test_appctx.py b/tests/test_appctx.py index 2430f577..0c291b87 100644 --- a/tests/test_appctx.py +++ b/tests/test_appctx.py @@ -9,6 +9,8 @@ :license: BSD, see LICENSE for more details. """ +import pytest + import flask import unittest from tests import TestFlask @@ -27,29 +29,29 @@ class TestAppContext(TestFlask): with app.app_context(): rv = flask.url_for('index') - self.assert_equal(rv, 'https://localhost/') + assert rv == 'https://localhost/' def test_url_generation_requires_server_name(self): app = flask.Flask(__name__) with app.app_context(): - with self.assert_raises(RuntimeError): + with pytest.raises(RuntimeError): flask.url_for('index') def test_url_generation_without_context_fails(self): - with self.assert_raises(RuntimeError): + with pytest.raises(RuntimeError): flask.url_for('index') def test_request_context_means_app_context(self): app = flask.Flask(__name__) with app.test_request_context(): - self.assert_equal(flask.current_app._get_current_object(), app) - self.assert_equal(flask._app_ctx_stack.top, None) + assert flask.current_app._get_current_object() == app + assert flask._app_ctx_stack.top == None def test_app_context_provides_current_app(self): app = flask.Flask(__name__) with app.app_context(): - self.assert_equal(flask.current_app._get_current_object(), app) - self.assert_equal(flask._app_ctx_stack.top, None) + assert flask.current_app._get_current_object() == app + assert flask._app_ctx_stack.top == None def test_app_tearing_down(self): cleanup_stuff = [] @@ -61,7 +63,7 @@ class TestAppContext(TestFlask): with app.app_context(): pass - self.assert_equal(cleanup_stuff, [None]) + assert cleanup_stuff == [None] def test_app_tearing_down_with_previous_exception(self): cleanup_stuff = [] @@ -78,7 +80,7 @@ class TestAppContext(TestFlask): with app.app_context(): pass - self.assert_equal(cleanup_stuff, [None]) + assert cleanup_stuff == [None] def test_custom_app_ctx_globals_class(self): class CustomRequestGlobals(object): @@ -87,8 +89,7 @@ class TestAppContext(TestFlask): app = flask.Flask(__name__) app.app_ctx_globals_class = CustomRequestGlobals with app.app_context(): - self.assert_equal( - flask.render_template_string('{{ g.spam }}'), 'eggs') + assert flask.render_template_string('{{ g.spam }}') == 'eggs' def test_context_refcounts(self): called = [] @@ -104,12 +105,14 @@ class TestAppContext(TestFlask): with flask._app_ctx_stack.top: with flask._request_ctx_stack.top: pass - self.assert_true(flask._request_ctx_stack.top.request.environ - ['werkzeug.request'] is not None) + env = flask._request_ctx_stack.top.request.environ + assert env['werkzeug.request'] is not None return u'' c = app.test_client() - c.get('/') - self.assert_equal(called, ['request', 'app']) + res = c.get('/') + assert res.status_code == 200 + assert res.data == u'' + assert called == ['request', 'app'] def suite(): diff --git a/tests/test_basic.py b/tests/test_basic.py index c06907e6..eff5419d 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -9,6 +9,8 @@ :license: BSD, see LICENSE for more details. """ +import pytest + import re import uuid import time @@ -32,8 +34,8 @@ class TestBasicFunctionality(TestFlask): def index(): return 'Hello World' rv = app.test_client().open('/', method='OPTIONS') - self.assert_equal(sorted(rv.allow), ['GET', 'HEAD', 'OPTIONS', 'POST']) - self.assert_equal(rv.data, b'') + assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST'] + assert rv.data == b'' def test_options_on_multiple_rules(self): app = flask.Flask(__name__) @@ -44,7 +46,7 @@ class TestBasicFunctionality(TestFlask): def index_put(): return 'Aha!' rv = app.test_client().open('/', method='OPTIONS') - self.assert_equal(sorted(rv.allow), ['GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']) + assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] def test_options_handling_disabled(self): app = flask.Flask(__name__) @@ -53,7 +55,7 @@ class TestBasicFunctionality(TestFlask): index.provide_automatic_options = False app.route('/')(index) rv = app.test_client().open('/', method='OPTIONS') - self.assert_equal(rv.status_code, 405) + assert rv.status_code == 405 app = flask.Flask(__name__) def index2(): @@ -61,7 +63,7 @@ class TestBasicFunctionality(TestFlask): index2.provide_automatic_options = True app.route('/', methods=['OPTIONS'])(index2) rv = app.test_client().open('/', method='OPTIONS') - self.assert_equal(sorted(rv.allow), ['OPTIONS']) + assert sorted(rv.allow) == ['OPTIONS'] def test_request_dispatching(self): app = flask.Flask(__name__) @@ -73,22 +75,22 @@ class TestBasicFunctionality(TestFlask): return flask.request.method c = app.test_client() - self.assert_equal(c.get('/').data, b'GET') + assert c.get('/').data == b'GET' rv = c.post('/') - self.assert_equal(rv.status_code, 405) - self.assert_equal(sorted(rv.allow), ['GET', 'HEAD', 'OPTIONS']) + assert rv.status_code == 405 + assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS'] rv = c.head('/') - self.assert_equal(rv.status_code, 200) - self.assert_false(rv.data) # head truncates - self.assert_equal(c.post('/more').data, b'POST') - self.assert_equal(c.get('/more').data, b'GET') + assert rv.status_code == 200 + assert not rv.data # head truncates + assert c.post('/more').data == b'POST' + assert c.get('/more').data == b'GET' rv = c.delete('/more') - self.assert_equal(rv.status_code, 405) - self.assert_equal(sorted(rv.allow), ['GET', 'HEAD', 'OPTIONS', 'POST']) + assert rv.status_code == 405 + assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST'] def test_disallow_string_for_allowed_methods(self): app = flask.Flask(__name__) - with self.assert_raises(TypeError): + with pytest.raises(TypeError): @app.route('/', methods='GET POST') def index(): return "Hey" @@ -104,18 +106,18 @@ class TestBasicFunctionality(TestFlask): app.add_url_rule('/more', 'more', more, methods=['GET', 'POST']) c = app.test_client() - self.assert_equal(c.get('/').data, b'GET') + assert c.get('/').data == b'GET' rv = c.post('/') - self.assert_equal(rv.status_code, 405) - self.assert_equal(sorted(rv.allow), ['GET', 'HEAD', 'OPTIONS']) + assert rv.status_code == 405 + assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS'] rv = c.head('/') - self.assert_equal(rv.status_code, 200) - self.assert_false(rv.data) # head truncates - self.assert_equal(c.post('/more').data, b'POST') - self.assert_equal(c.get('/more').data, b'GET') + assert rv.status_code == 200 + assert not rv.data # head truncates + assert c.post('/more').data == b'POST' + assert c.get('/more').data == b'GET' rv = c.delete('/more') - self.assert_equal(rv.status_code, 405) - self.assert_equal(sorted(rv.allow), ['GET', 'HEAD', 'OPTIONS', 'POST']) + assert rv.status_code == 405 + assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST'] def test_werkzeug_routing(self): from werkzeug.routing import Submount, Rule @@ -132,8 +134,8 @@ class TestBasicFunctionality(TestFlask): app.view_functions['index'] = index c = app.test_client() - self.assert_equal(c.get('/foo/').data, b'index') - self.assert_equal(c.get('/foo/bar').data, b'bar') + assert c.get('/foo/').data == b'index' + assert c.get('/foo/bar').data == b'bar' def test_endpoint_decorator(self): from werkzeug.routing import Submount, Rule @@ -152,8 +154,8 @@ class TestBasicFunctionality(TestFlask): return 'index' c = app.test_client() - self.assert_equal(c.get('/foo/').data, b'index') - self.assert_equal(c.get('/foo/bar').data, b'bar') + assert c.get('/foo/').data == b'index' + assert c.get('/foo/bar').data == b'bar' def test_session(self): app = flask.Flask(__name__) @@ -167,8 +169,8 @@ class TestBasicFunctionality(TestFlask): return flask.session['value'] c = app.test_client() - self.assert_equal(c.post('/set', data={'value': '42'}).data, b'value set') - self.assert_equal(c.get('/get').data, b'42') + assert c.post('/set', data={'value': '42'}).data == b'value set' + assert c.get('/get').data == b'42' def test_session_using_server_name(self): app = flask.Flask(__name__) @@ -181,8 +183,8 @@ class TestBasicFunctionality(TestFlask): flask.session['testing'] = 42 return 'Hello World' rv = app.test_client().get('/', 'http://example.com/') - self.assert_in('domain=.example.com', rv.headers['set-cookie'].lower()) - self.assert_in('httponly', rv.headers['set-cookie'].lower()) + assert 'domain=.example.com' in rv.headers['set-cookie'].lower() + assert 'httponly' in rv.headers['set-cookie'].lower() def test_session_using_server_name_and_port(self): app = flask.Flask(__name__) @@ -195,8 +197,8 @@ class TestBasicFunctionality(TestFlask): flask.session['testing'] = 42 return 'Hello World' rv = app.test_client().get('/', 'http://example.com:8080/') - self.assert_in('domain=.example.com', rv.headers['set-cookie'].lower()) - self.assert_in('httponly', rv.headers['set-cookie'].lower()) + assert 'domain=.example.com' in rv.headers['set-cookie'].lower() + assert 'httponly' in rv.headers['set-cookie'].lower() def test_session_using_server_name_port_and_path(self): app = flask.Flask(__name__) @@ -210,9 +212,9 @@ class TestBasicFunctionality(TestFlask): flask.session['testing'] = 42 return 'Hello World' rv = app.test_client().get('/', 'http://example.com:8080/foo') - self.assert_in('domain=example.com', rv.headers['set-cookie'].lower()) - self.assert_in('path=/foo', rv.headers['set-cookie'].lower()) - self.assert_in('httponly', rv.headers['set-cookie'].lower()) + assert 'domain=example.com' in rv.headers['set-cookie'].lower() + assert 'path=/foo' in rv.headers['set-cookie'].lower() + assert 'httponly' in rv.headers['set-cookie'].lower() def test_session_using_application_root(self): class PrefixPathMiddleware(object): @@ -234,7 +236,7 @@ class TestBasicFunctionality(TestFlask): flask.session['testing'] = 42 return 'Hello World' rv = app.test_client().get('/', 'http://example.com:8080/') - self.assert_in('path=/bar', rv.headers['set-cookie'].lower()) + assert 'path=/bar' in rv.headers['set-cookie'].lower() def test_session_using_session_settings(self): app = flask.Flask(__name__) @@ -253,10 +255,10 @@ class TestBasicFunctionality(TestFlask): return 'Hello World' rv = app.test_client().get('/', 'http://www.example.com:8080/test/') cookie = rv.headers['set-cookie'].lower() - self.assert_in('domain=.example.com', cookie) - self.assert_in('path=/', cookie) - self.assert_in('secure', cookie) - self.assert_not_in('httponly', cookie) + assert 'domain=.example.com' in cookie + assert 'path=/' in cookie + assert 'secure' in cookie + assert 'httponly' not in cookie def test_missing_session(self): app = flask.Flask(__name__) @@ -264,11 +266,11 @@ class TestBasicFunctionality(TestFlask): try: f(*args, **kwargs) except RuntimeError as e: - self.assert_true(e.args and 'session is unavailable' in e.args[0]) + assert e.args and 'session is unavailable' in e.args[0] else: - self.assert_true(False, 'expected exception') + assert False, 'expected exception' with app.test_request_context(): - self.assert_true(flask.session.get('missing_key') is None) + assert flask.session.get('missing_key') is None expect_exception(flask.session.__setitem__, 'foo', 42) expect_exception(flask.session.pop, 'foo') @@ -288,22 +290,22 @@ class TestBasicFunctionality(TestFlask): client = app.test_client() rv = client.get('/') - self.assert_in('set-cookie', rv.headers) + assert 'set-cookie' in rv.headers match = re.search(r'\bexpires=([^;]+)(?i)', rv.headers['set-cookie']) expires = parse_date(match.group()) expected = datetime.utcnow() + app.permanent_session_lifetime - self.assert_equal(expires.year, expected.year) - self.assert_equal(expires.month, expected.month) - self.assert_equal(expires.day, expected.day) + assert expires.year == expected.year + assert expires.month == expected.month + assert expires.day == expected.day rv = client.get('/test') - self.assert_equal(rv.data, b'True') + assert rv.data == b'True' permanent = False rv = app.test_client().get('/') - self.assert_in('set-cookie', rv.headers) + assert 'set-cookie' in rv.headers match = re.search(r'\bexpires=([^;]+)', rv.headers['set-cookie']) - self.assert_true(match is None) + assert match is None def test_session_stored_last(self): app = flask.Flask(__name__) @@ -319,8 +321,8 @@ class TestBasicFunctionality(TestFlask): return repr(flask.session.get('foo')) c = app.test_client() - self.assert_equal(c.get('/').data, b'None') - self.assert_equal(c.get('/').data, b'42') + assert c.get('/').data == b'None' + assert c.get('/').data == b'42' def test_session_special_types(self): app = flask.Flask(__name__) @@ -345,13 +347,13 @@ class TestBasicFunctionality(TestFlask): c = app.test_client() c.get('/') rv = pickle.loads(c.get('/').data) - self.assert_equal(rv['m'], flask.Markup('Hello!')) - self.assert_equal(type(rv['m']), flask.Markup) - self.assert_equal(rv['dt'], now) - self.assert_equal(rv['u'], the_uuid) - self.assert_equal(rv['b'], b'\xff') - self.assert_equal(type(rv['b']), bytes) - self.assert_equal(rv['t'], (1, 2, 3)) + assert rv['m'] == flask.Markup('Hello!') + assert type(rv['m']) == flask.Markup + assert rv['dt'] == now + assert rv['u'] == the_uuid + assert rv['b'] == b'\xff' + assert type(rv['b']) == bytes + assert rv['t'] == (1, 2, 3) def test_session_cookie_setting(self): app = flask.Flask(__name__) @@ -371,14 +373,14 @@ class TestBasicFunctionality(TestFlask): def run_test(expect_header): with app.test_client() as c: - self.assert_equal(c.get('/bump').data, b'1') - self.assert_equal(c.get('/bump').data, b'2') - self.assert_equal(c.get('/bump').data, b'3') + assert c.get('/bump').data == b'1' + assert c.get('/bump').data == b'2' + assert c.get('/bump').data == b'3' rv = c.get('/read') set_cookie = rv.headers.get('set-cookie') - self.assert_equal(set_cookie is not None, expect_header) - self.assert_equal(rv.data, b'3') + assert (set_cookie is not None) == expect_header + assert rv.data == b'3' is_permanent = True app.config['SESSION_REFRESH_EACH_REQUEST'] = True @@ -401,12 +403,12 @@ class TestBasicFunctionality(TestFlask): app.secret_key = 'testkey' with app.test_request_context(): - self.assert_false(flask.session.modified) + assert not flask.session.modified flask.flash('Zap') flask.session.modified = False flask.flash('Zip') - self.assert_true(flask.session.modified) - self.assert_equal(list(flask.get_flashed_messages()), ['Zap', 'Zip']) + assert flask.session.modified + assert list(flask.get_flashed_messages()) == ['Zap', 'Zip'] def test_extended_flashing(self): # Be sure app.testing=True below, else tests can fail silently. @@ -429,42 +431,45 @@ class TestBasicFunctionality(TestFlask): @app.route('/test/') def test(): messages = flask.get_flashed_messages() - self.assert_equal(len(messages), 3) - self.assert_equal(messages[0], u'Hello World') - self.assert_equal(messages[1], u'Hello World') - self.assert_equal(messages[2], flask.Markup(u'Testing')) + assert list(messages) == [ + u'Hello World', + u'Hello World', + flask.Markup(u'Testing') + ] return '' @app.route('/test_with_categories/') def test_with_categories(): messages = flask.get_flashed_messages(with_categories=True) - self.assert_equal(len(messages), 3) - self.assert_equal(messages[0], ('message', u'Hello World')) - self.assert_equal(messages[1], ('error', u'Hello World')) - self.assert_equal(messages[2], ('warning', flask.Markup(u'Testing'))) + assert len(messages) == 3 + assert list(messages) == [ + ('message', u'Hello World'), + ('error', u'Hello World'), + ('warning', flask.Markup(u'Testing')) + ] return '' @app.route('/test_filter/') def test_filter(): messages = flask.get_flashed_messages(category_filter=['message'], with_categories=True) - self.assert_equal(len(messages), 1) - self.assert_equal(messages[0], ('message', u'Hello World')) + assert list(messages) == [('message', u'Hello World')] return '' @app.route('/test_filters/') def test_filters(): messages = flask.get_flashed_messages(category_filter=['message', 'warning'], with_categories=True) - self.assert_equal(len(messages), 2) - self.assert_equal(messages[0], ('message', u'Hello World')) - self.assert_equal(messages[1], ('warning', flask.Markup(u'Testing'))) + assert list(messages) == [ + ('message', u'Hello World'), + ('warning', flask.Markup(u'Testing')) + ] return '' @app.route('/test_filters_without_returning_categories/') def test_filters2(): messages = flask.get_flashed_messages(category_filter=['message', 'warning']) - self.assert_equal(len(messages), 2) - self.assert_equal(messages[0], u'Hello World') - self.assert_equal(messages[1], flask.Markup(u'Testing')) + assert len(messages) == 2 + assert messages[0] == u'Hello World' + assert messages[1] == flask.Markup(u'Testing') return '' # Create new test client on each test to clean flashed messages. @@ -502,13 +507,13 @@ class TestBasicFunctionality(TestFlask): return response @app.route('/') def index(): - self.assert_in('before', evts) - self.assert_not_in('after', evts) + assert 'before' in evts + assert 'after' not in evts return 'request' - self.assert_not_in('after', evts) + assert 'after' not in evts rv = app.test_client().get('/').data - self.assert_in('after', evts) - self.assert_equal(rv, b'request|after') + assert 'after' in evts + assert rv == b'request|after' def test_after_request_processing(self): app = flask.Flask(__name__) @@ -522,8 +527,8 @@ class TestBasicFunctionality(TestFlask): return 'Test' c = app.test_client() resp = c.get('/') - self.assert_equal(resp.status_code, 200) - self.assert_equal(resp.headers['X-Foo'], 'a header') + assert resp.status_code == 200 + assert resp.headers['X-Foo'] == 'a header' def test_teardown_request_handler(self): called = [] @@ -536,9 +541,9 @@ class TestBasicFunctionality(TestFlask): def root(): return "Response" rv = app.test_client().get('/') - self.assert_equal(rv.status_code, 200) - self.assert_in(b'Response', rv.data) - self.assert_equal(len(called), 1) + assert rv.status_code == 200 + assert b'Response' in rv.data + assert len(called) == 1 def test_teardown_request_handler_debug_mode(self): called = [] @@ -552,9 +557,9 @@ class TestBasicFunctionality(TestFlask): def root(): return "Response" rv = app.test_client().get('/') - self.assert_equal(rv.status_code, 200) - self.assert_in(b'Response', rv.data) - self.assert_equal(len(called), 1) + assert rv.status_code == 200 + assert b'Response' in rv.data + assert len(called) == 1 def test_teardown_request_handler_error(self): called = [] @@ -562,7 +567,7 @@ class TestBasicFunctionality(TestFlask): app.config['LOGGER_HANDLER_POLICY'] = 'never' @app.teardown_request def teardown_request1(exc): - self.assert_equal(type(exc), ZeroDivisionError) + assert type(exc) == ZeroDivisionError called.append(True) # This raises a new error and blows away sys.exc_info(), so we can # test that all teardown_requests get passed the same original @@ -573,7 +578,7 @@ class TestBasicFunctionality(TestFlask): pass @app.teardown_request def teardown_request2(exc): - self.assert_equal(type(exc), ZeroDivisionError) + assert type(exc) == ZeroDivisionError called.append(True) # This raises a new error and blows away sys.exc_info(), so we can # test that all teardown_requests get passed the same original @@ -586,9 +591,9 @@ class TestBasicFunctionality(TestFlask): def fails(): 1 // 0 rv = app.test_client().get('/') - self.assert_equal(rv.status_code, 500) - self.assert_in(b'Internal Server Error', rv.data) - self.assert_equal(len(called), 2) + assert rv.status_code == 500 + assert b'Internal Server Error' in rv.data + assert len(called) == 2 def test_before_after_request_order(self): called = [] @@ -617,8 +622,8 @@ class TestBasicFunctionality(TestFlask): def index(): return '42' rv = app.test_client().get('/') - self.assert_equal(rv.data, b'42') - self.assert_equal(called, [1, 2, 3, 4, 5, 6]) + assert rv.data == b'42' + assert called == [1, 2, 3, 4, 5, 6] def test_error_handling(self): app = flask.Flask(__name__) @@ -643,14 +648,14 @@ class TestBasicFunctionality(TestFlask): flask.abort(403) c = app.test_client() rv = c.get('/') - self.assert_equal(rv.status_code, 404) - self.assert_equal(rv.data, b'not found') + assert rv.status_code == 404 + assert rv.data == b'not found' rv = c.get('/error') - self.assert_equal(rv.status_code, 500) - self.assert_equal(b'internal server error', rv.data) + assert rv.status_code == 500 + assert b'internal server error' == rv.data rv = c.get('/forbidden') - self.assert_equal(rv.status_code, 403) - self.assert_equal(b'forbidden', rv.data) + assert rv.status_code == 403 + assert b'forbidden' == rv.data def test_before_request_and_routing_errors(self): app = flask.Flask(__name__) @@ -661,8 +666,8 @@ class TestBasicFunctionality(TestFlask): def return_something(error): return flask.g.something, 404 rv = app.test_client().get('/') - self.assert_equal(rv.status_code, 404) - self.assert_equal(rv.data, b'value') + assert rv.status_code == 404 + assert rv.data == b'value' def test_user_error_handling(self): class MyException(Exception): @@ -671,14 +676,14 @@ class TestBasicFunctionality(TestFlask): app = flask.Flask(__name__) @app.errorhandler(MyException) def handle_my_exception(e): - self.assert_true(isinstance(e, MyException)) + assert isinstance(e, MyException) return '42' @app.route('/') def index(): raise MyException() c = app.test_client() - self.assert_equal(c.get('/').data, b'42') + assert c.get('/').data == b'42' def test_http_error_subclass_handling(self): class ForbiddenSubclass(Forbidden): @@ -687,12 +692,12 @@ class TestBasicFunctionality(TestFlask): app = flask.Flask(__name__) @app.errorhandler(ForbiddenSubclass) def handle_forbidden_subclass(e): - self.assert_true(isinstance(e, ForbiddenSubclass)) + assert isinstance(e, ForbiddenSubclass) return 'banana' @app.errorhandler(403) def handle_forbidden_subclass(e): - self.assert_false(isinstance(e, ForbiddenSubclass)) - self.assert_true(isinstance(e, Forbidden)) + assert not isinstance(e, ForbiddenSubclass) + assert isinstance(e, Forbidden) return 'apple' @app.route('/1') @@ -706,9 +711,9 @@ class TestBasicFunctionality(TestFlask): raise Forbidden() c = app.test_client() - self.assert_equal(c.get('/1').data, b'banana') - self.assert_equal(c.get('/2').data, b'apple') - self.assert_equal(c.get('/3').data, b'apple') + assert c.get('/1').data == b'banana' + assert c.get('/2').data == b'apple' + assert c.get('/3').data == b'apple' def test_trapping_of_bad_request_key_errors(self): app = flask.Flask(__name__) @@ -717,16 +722,16 @@ class TestBasicFunctionality(TestFlask): def fail(): flask.request.form['missing_key'] c = app.test_client() - self.assert_equal(c.get('/fail').status_code, 400) + assert c.get('/fail').status_code == 400 app.config['TRAP_BAD_REQUEST_ERRORS'] = True c = app.test_client() try: c.get('/fail') except KeyError as e: - self.assert_true(isinstance(e, BadRequest)) + assert isinstance(e, BadRequest) else: - self.fail('Expected exception') + assert False, 'Expected exception' def test_trapping_of_all_http_exceptions(self): app = flask.Flask(__name__) @@ -742,7 +747,7 @@ class TestBasicFunctionality(TestFlask): except NotFound as e: pass else: - self.fail('Expected exception') + assert False, 'Expected exception' def test_enctype_debug_helper(self): from flask.debughelpers import DebugFilesKeyError @@ -759,10 +764,10 @@ class TestBasicFunctionality(TestFlask): try: c.post('/fail', data={'foo': 'index.txt'}) except DebugFilesKeyError as e: - self.assert_in('no file contents were transmitted', str(e)) - self.assert_in('This was submitted: "index.txt"', str(e)) + assert 'no file contents were transmitted' in str(e) + assert 'This was submitted: "index.txt"' in str(e) else: - self.fail('Expected exception') + assert False, 'Expected exception' def test_response_creation(self): app = flask.Flask(__name__) @@ -795,67 +800,67 @@ class TestBasicFunctionality(TestFlask): } c = app.test_client() - self.assert_equal(c.get('/unicode').data, u'Hällo Wörld'.encode('utf-8')) - self.assert_equal(c.get('/string').data, u'Hällo Wörld'.encode('utf-8')) + assert c.get('/unicode').data == u'Hällo Wörld'.encode('utf-8') + assert c.get('/string').data == u'Hällo Wörld'.encode('utf-8') rv = c.get('/args') - self.assert_equal(rv.data, b'Meh') - self.assert_equal(rv.headers['X-Foo'], 'Testing') - self.assert_equal(rv.status_code, 400) - self.assert_equal(rv.mimetype, 'text/plain') + assert rv.data == b'Meh' + assert rv.headers['X-Foo'] == 'Testing' + assert rv.status_code == 400 + assert rv.mimetype == 'text/plain' rv2 = c.get('/two_args') - self.assert_equal(rv2.data, b'Hello') - self.assert_equal(rv2.headers['X-Foo'], 'Test') - self.assert_equal(rv2.status_code, 200) - self.assert_equal(rv2.mimetype, 'text/plain') + assert rv2.data == b'Hello' + assert rv2.headers['X-Foo'] == 'Test' + assert rv2.status_code == 200 + assert rv2.mimetype == 'text/plain' rv3 = c.get('/args_status') - self.assert_equal(rv3.data, b'Hi, status!') - self.assert_equal(rv3.status_code, 400) - self.assert_equal(rv3.mimetype, 'text/html') + assert rv3.data == b'Hi, status!' + assert rv3.status_code == 400 + assert rv3.mimetype == 'text/html' rv4 = c.get('/args_header') - self.assert_equal(rv4.data, b'Hello world') - self.assert_equal(rv4.headers['X-Foo'], 'Bar') - self.assert_equal(rv4.headers['X-Bar'], 'Foo') - self.assert_equal(rv4.status_code, 404) + assert rv4.data == b'Hello world' + assert rv4.headers['X-Foo'] == 'Bar' + assert rv4.headers['X-Bar'] == 'Foo' + assert rv4.status_code == 404 def test_make_response(self): app = flask.Flask(__name__) with app.test_request_context(): rv = flask.make_response() - self.assert_equal(rv.status_code, 200) - self.assert_equal(rv.data, b'') - self.assert_equal(rv.mimetype, 'text/html') + assert rv.status_code == 200 + assert rv.data == b'' + assert rv.mimetype == 'text/html' rv = flask.make_response('Awesome') - self.assert_equal(rv.status_code, 200) - self.assert_equal(rv.data, b'Awesome') - self.assert_equal(rv.mimetype, 'text/html') + assert rv.status_code == 200 + assert rv.data == b'Awesome' + assert rv.mimetype == 'text/html' rv = flask.make_response('W00t', 404) - self.assert_equal(rv.status_code, 404) - self.assert_equal(rv.data, b'W00t') - self.assert_equal(rv.mimetype, 'text/html') + assert rv.status_code == 404 + assert rv.data == b'W00t' + assert rv.mimetype == 'text/html' def test_make_response_with_response_instance(self): app = flask.Flask(__name__) with app.test_request_context(): rv = flask.make_response( flask.jsonify({'msg': 'W00t'}), 400) - self.assert_equal(rv.status_code, 400) - self.assert_equal(rv.data, b'{\n "msg": "W00t"\n}') - self.assert_equal(rv.mimetype, 'application/json') + assert rv.status_code == 400 + assert rv.data == b'{\n "msg": "W00t"\n}' + assert rv.mimetype == 'application/json' rv = flask.make_response( flask.Response(''), 400) - self.assert_equal(rv.status_code, 400) - self.assert_equal(rv.data, b'') - self.assert_equal(rv.mimetype, 'text/html') + assert rv.status_code == 400 + assert rv.data == b'' + assert rv.mimetype == 'text/html' rv = flask.make_response( flask.Response('', headers={'Content-Type': 'text/html'}), 400, [('X-Foo', 'bar')]) - self.assert_equal(rv.status_code, 400) - self.assert_equal(rv.headers['Content-Type'], 'text/html') - self.assert_equal(rv.headers['X-Foo'], 'bar') + assert rv.status_code == 400 + assert rv.headers['Content-Type'] == 'text/html' + assert rv.headers['X-Foo'] == 'bar' def test_url_generation(self): app = flask.Flask(__name__) @@ -863,16 +868,16 @@ class TestBasicFunctionality(TestFlask): def hello(): pass with app.test_request_context(): - self.assert_equal(flask.url_for('hello', name='test x'), '/hello/test%20x') - self.assert_equal(flask.url_for('hello', name='test x', _external=True), - 'http://localhost/hello/test%20x') + assert flask.url_for('hello', name='test x') == '/hello/test%20x' + assert flask.url_for('hello', name='test x', _external=True) == \ + 'http://localhost/hello/test%20x' def test_build_error_handler(self): app = flask.Flask(__name__) # Test base case, a URL which results in a BuildError. with app.test_request_context(): - self.assert_raises(BuildError, flask.url_for, 'spam') + pytest.raises(BuildError, flask.url_for, 'spam') # Verify the error is re-raised if not the current exception. try: @@ -883,7 +888,7 @@ class TestBasicFunctionality(TestFlask): try: raise RuntimeError('Test case where BuildError is not current.') except RuntimeError: - self.assert_raises(BuildError, app.handle_url_build_error, error, 'spam', {}) + pytest.raises(BuildError, app.handle_url_build_error, error, 'spam', {}) # Test a custom handler. def handler(error, endpoint, values): @@ -891,7 +896,7 @@ class TestBasicFunctionality(TestFlask): return '/test_handler/' app.url_build_error_handlers.append(handler) with app.test_request_context(): - self.assert_equal(flask.url_for('spam'), '/test_handler/') + assert flask.url_for('spam') == '/test_handler/' def test_custom_converters(self): from werkzeug.routing import BaseConverter @@ -907,17 +912,17 @@ class TestBasicFunctionality(TestFlask): def index(args): return '|'.join(args) c = app.test_client() - self.assert_equal(c.get('/1,2,3').data, b'1|2|3') + assert c.get('/1,2,3').data == b'1|2|3' def test_static_files(self): app = flask.Flask(__name__) app.testing = True rv = app.test_client().get('/static/index.html') - self.assert_equal(rv.status_code, 200) - self.assert_equal(rv.data.strip(), b'

Hello World!

') + assert rv.status_code == 200 + assert rv.data.strip() == b'

Hello World!

' with app.test_request_context(): - self.assert_equal(flask.url_for('static', filename='index.html'), - '/static/index.html') + assert flask.url_for('static', filename='index.html') == \ + '/static/index.html' rv.close() def test_none_response(self): @@ -929,14 +934,14 @@ class TestBasicFunctionality(TestFlask): try: app.test_client().get('/') except ValueError as e: - self.assert_equal(str(e), 'View function did not return a response') + assert str(e) == 'View function did not return a response' pass else: - self.assert_true("Expected ValueError") + assert "Expected ValueError" def test_request_locals(self): - self.assert_equal(repr(flask.g), '') - self.assert_false(flask.g) + assert repr(flask.g) == '' + assert not flask.g def test_test_app_proper_environ(self): app = flask.Flask(__name__) @@ -952,42 +957,46 @@ class TestBasicFunctionality(TestFlask): return 'Foo SubDomain' rv = app.test_client().get('/') - self.assert_equal(rv.data, b'Foo') + assert rv.data == b'Foo' rv = app.test_client().get('/', 'http://localhost.localdomain:5000') - self.assert_equal(rv.data, b'Foo') + assert rv.data == b'Foo' rv = app.test_client().get('/', 'https://localhost.localdomain:5000') - self.assert_equal(rv.data, b'Foo') + assert rv.data == b'Foo' app.config.update(SERVER_NAME='localhost.localdomain') rv = app.test_client().get('/', 'https://localhost.localdomain') - self.assert_equal(rv.data, b'Foo') + assert rv.data == b'Foo' try: app.config.update(SERVER_NAME='localhost.localdomain:443') rv = app.test_client().get('/', 'https://localhost.localdomain') # Werkzeug 0.8 - self.assert_equal(rv.status_code, 404) + assert rv.status_code == 404 except ValueError as e: # Werkzeug 0.7 - self.assert_equal(str(e), "the server name provided " + - "('localhost.localdomain:443') does not match the " + \ - "server name from the WSGI environment ('localhost.localdomain')") + assert str(e) == ( + "the server name provided " + "('localhost.localdomain:443') does not match the " + "server name from the WSGI environment ('localhost.localdomain')" + ) try: app.config.update(SERVER_NAME='localhost.localdomain') rv = app.test_client().get('/', 'http://foo.localhost') # Werkzeug 0.8 - self.assert_equal(rv.status_code, 404) + assert rv.status_code == 404 except ValueError as e: # Werkzeug 0.7 - self.assert_equal(str(e), "the server name provided " + \ - "('localhost.localdomain') does not match the " + \ - "server name from the WSGI environment ('foo.localhost')") + assert str(e) == ( + "the server name provided " + "('localhost.localdomain') does not match the " + "server name from the WSGI environment ('foo.localhost')" + ) rv = app.test_client().get('/', 'http://foo.localhost.localdomain') - self.assert_equal(rv.data, b'Foo SubDomain') + assert rv.data == b'Foo SubDomain' def test_exception_propagation(self): def apprunner(configkey): @@ -1004,9 +1013,9 @@ class TestBasicFunctionality(TestFlask): except Exception: pass else: - self.fail('expected exception') + assert False, 'expected exception' else: - self.assert_equal(c.get('/').status_code, 500) + assert c.get('/').status_code == 500 # we have to run this test in an isolated thread because if the # debug flag is set to true and an exception happens the context is @@ -1023,18 +1032,18 @@ class TestBasicFunctionality(TestFlask): @app.before_request def always_first(): flask.request.form['myfile'] - self.assert_true(False) + assert False @app.route('/accept', methods=['POST']) def accept_file(): flask.request.form['myfile'] - self.assert_true(False) + assert False @app.errorhandler(413) def catcher(error): return '42' c = app.test_client() rv = c.post('/accept', data={'myfile': 'foo' * 100}) - self.assert_equal(rv.data, b'42') + assert rv.data == b'42' def test_url_processors(self): app = flask.Flask(__name__) @@ -1063,9 +1072,9 @@ class TestBasicFunctionality(TestFlask): c = app.test_client() - self.assert_equal(c.get('/de/').data, b'/de/about') - self.assert_equal(c.get('/de/about').data, b'/foo') - self.assert_equal(c.get('/foo').data, b'/en/about') + assert c.get('/de/').data == b'/de/about' + assert c.get('/de/about').data == b'/foo' + assert c.get('/foo').data == b'/en/about' def test_inject_blueprint_url_defaults(self): app = flask.Flask(__name__) @@ -1083,12 +1092,12 @@ class TestBasicFunctionality(TestFlask): values = dict() app.inject_url_defaults('foo.bar.baz.view', values) expected = dict(page='login') - self.assert_equal(values, expected) + assert values == expected with app.test_request_context('/somepage'): url = flask.url_for('foo.bar.baz.view') expected = '/login' - self.assert_equal(url, expected) + assert url == expected def test_nonascii_pathinfo(self): app = flask.Flask(__name__) @@ -1100,7 +1109,7 @@ class TestBasicFunctionality(TestFlask): c = app.test_client() rv = c.get(u'/киртест') - self.assert_equal(rv.data, b'Hello World!') + assert rv.data == b'Hello World!' def test_debug_mode_complains_after_first_request(self): app = flask.Flask(__name__) @@ -1108,23 +1117,23 @@ class TestBasicFunctionality(TestFlask): @app.route('/') def index(): return 'Awesome' - self.assert_false(app.got_first_request) - self.assert_equal(app.test_client().get('/').data, b'Awesome') + assert not app.got_first_request + assert app.test_client().get('/').data == b'Awesome' try: @app.route('/foo') def broken(): return 'Meh' except AssertionError as e: - self.assert_in('A setup function was called', str(e)) + assert 'A setup function was called' in str(e) else: - self.fail('Expected exception') + assert False, 'Expected exception' app.debug = False @app.route('/foo') def working(): return 'Meh' - self.assert_equal(app.test_client().get('/foo').data, b'Meh') - self.assert_true(app.got_first_request) + assert app.test_client().get('/foo').data == b'Meh' + assert app.got_first_request def test_before_first_request_functions(self): got = [] @@ -1134,10 +1143,10 @@ class TestBasicFunctionality(TestFlask): got.append(42) c = app.test_client() c.get('/') - self.assert_equal(got, [42]) + assert got == [42] c.get('/') - self.assert_equal(got, [42]) - self.assert_true(app.got_first_request) + assert got == [42] + assert app.got_first_request def test_before_first_request_functions_concurrent(self): got = [] @@ -1151,13 +1160,13 @@ class TestBasicFunctionality(TestFlask): c = app.test_client() def get_and_assert(): c.get("/") - self.assert_equal(got, [42]) + assert got == [42] t = Thread(target=get_and_assert) t.start() get_and_assert() t.join() - self.assert_true(app.got_first_request) + assert app.got_first_request def test_routing_redirect_debugging(self): app = flask.Flask(__name__) @@ -1169,19 +1178,19 @@ class TestBasicFunctionality(TestFlask): try: c.post('/foo', data={}) except AssertionError as e: - self.assert_in('http://localhost/foo/', str(e)) - self.assert_in('Make sure to directly send your POST-request ' - 'to this URL', str(e)) + assert 'http://localhost/foo/' in str(e) + assert ('Make sure to directly send ' + 'your POST-request to this URL') in str(e) else: - self.fail('Expected exception') + assert False, 'Expected exception' rv = c.get('/foo', data={}, follow_redirects=True) - self.assert_equal(rv.data, b'success') + assert rv.data == b'success' app.debug = False with app.test_client() as c: rv = c.post('/foo', data={}, follow_redirects=True) - self.assert_equal(rv.data, b'success') + assert rv.data == b'success' def test_route_decorator_custom_endpoint(self): app = flask.Flask(__name__) @@ -1205,9 +1214,9 @@ class TestBasicFunctionality(TestFlask): assert flask.url_for('123') == '/bar/123' c = app.test_client() - self.assert_equal(c.get('/foo/').data, b'foo') - self.assert_equal(c.get('/bar/').data, b'bar') - self.assert_equal(c.get('/bar/123').data, b'123') + assert c.get('/foo/').data == b'foo' + assert c.get('/bar/').data == b'bar' + assert c.get('/bar/123').data == b'123' def test_preserve_only_once(self): app = flask.Flask(__name__) @@ -1219,15 +1228,15 @@ class TestBasicFunctionality(TestFlask): c = app.test_client() for x in range(3): - with self.assert_raises(ZeroDivisionError): + with pytest.raises(ZeroDivisionError): c.get('/fail') - self.assert_true(flask._request_ctx_stack.top is not None) - self.assert_true(flask._app_ctx_stack.top is not None) + assert flask._request_ctx_stack.top is not None + assert flask._app_ctx_stack.top is not None # implicit appctx disappears too flask._request_ctx_stack.top.pop() - self.assert_true(flask._request_ctx_stack.top is None) - self.assert_true(flask._app_ctx_stack.top is None) + assert flask._request_ctx_stack.top is None + assert flask._app_ctx_stack.top is None def test_preserve_remembers_exception(self): app = flask.Flask(__name__) @@ -1249,30 +1258,30 @@ class TestBasicFunctionality(TestFlask): c = app.test_client() # After this failure we did not yet call the teardown handler - with self.assert_raises(ZeroDivisionError): + with pytest.raises(ZeroDivisionError): c.get('/fail') - self.assert_equal(errors, []) + assert errors == [] # But this request triggers it, and it's an error c.get('/success') - self.assert_equal(len(errors), 2) - self.assert_true(isinstance(errors[0], ZeroDivisionError)) + assert len(errors) == 2 + assert isinstance(errors[0], ZeroDivisionError) # At this point another request does nothing. c.get('/success') - self.assert_equal(len(errors), 3) - self.assert_equal(errors[1], None) + assert len(errors) == 3 + assert errors[1] == None def test_get_method_on_g(self): app = flask.Flask(__name__) app.testing = True with app.app_context(): - self.assert_equal(flask.g.get('x'), None) - self.assert_equal(flask.g.get('x', 11), 11) + assert flask.g.get('x') == None + assert flask.g.get('x', 11) == 11 flask.g.x = 42 - self.assert_equal(flask.g.get('x'), 42) - self.assert_equal(flask.g.x, 42) + assert flask.g.get('x') == 42 + assert flask.g.x == 42 def test_g_iteration_protocol(self): app = flask.Flask(__name__) @@ -1281,9 +1290,9 @@ class TestBasicFunctionality(TestFlask): with app.app_context(): flask.g.foo = 23 flask.g.bar = 42 - self.assert_equal('foo' in flask.g, True) - self.assert_equal('foos' in flask.g, False) - self.assert_equal(sorted(flask.g), ['bar', 'foo']) + assert 'foo' in flask.g + assert 'foos' not in flask.g + assert sorted(flask.g) == ['bar', 'foo'] class TestSubdomain(TestFlask): @@ -1300,10 +1309,10 @@ class TestSubdomain(TestFlask): c = app.test_client() rv = c.get('/', 'http://localhost/') - self.assert_equal(rv.data, b'normal index') + assert rv.data == b'normal index' rv = c.get('/', 'http://test.localhost/') - self.assert_equal(rv.data, b'test index') + assert rv.data == b'test index' def test_subdomain_matching(self): app = flask.Flask(__name__) @@ -1314,7 +1323,7 @@ class TestSubdomain(TestFlask): c = app.test_client() rv = c.get('/', 'http://mitsuhiko.localhost/') - self.assert_equal(rv.data, b'index for mitsuhiko') + assert rv.data == b'index for mitsuhiko' def test_subdomain_matching_with_ports(self): app = flask.Flask(__name__) @@ -1325,7 +1334,7 @@ class TestSubdomain(TestFlask): c = app.test_client() rv = c.get('/', 'http://mitsuhiko.localhost:3000/') - self.assert_equal(rv.data, b'index for mitsuhiko') + assert rv.data == b'index for mitsuhiko' def test_multi_route_rules(self): app = flask.Flask(__name__) @@ -1336,9 +1345,9 @@ class TestSubdomain(TestFlask): return test rv = app.test_client().open('/') - self.assert_equal(rv.data, b'a') + assert rv.data == b'a' rv = app.test_client().open('/b/') - self.assert_equal(rv.data, b'b') + assert rv.data == b'b' def test_multi_route_class_views(self): class View(object): @@ -1352,6 +1361,6 @@ class TestSubdomain(TestFlask): app = flask.Flask(__name__) _ = View(app) rv = app.test_client().open('/') - self.assert_equal(rv.data, b'a') + assert rv.data == b'a' rv = app.test_client().open('/b/') - self.assert_equal(rv.data, b'b') + assert rv.data == b'b' diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index c8e85b4a..6f2be559 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -9,6 +9,8 @@ :license: BSD, see LICENSE for more details. """ +import pytest + import flask import unittest from tests import TestFlask @@ -55,9 +57,9 @@ class TestBlueprint(TestFlask): c = app.test_client() - self.assert_equal(c.get('/frontend-no').data, b'frontend says no') - self.assert_equal(c.get('/backend-no').data, b'backend says no') - self.assert_equal(c.get('/what-is-a-sideend').data, b'application itself says no') + assert c.get('/frontend-no').data == b'frontend says no' + assert c.get('/backend-no').data == b'backend says no' + assert c.get('/what-is-a-sideend').data == b'application itself says no' def test_blueprint_specific_user_error_handling(self): class MyDecoratorException(Exception): @@ -69,11 +71,11 @@ class TestBlueprint(TestFlask): @blue.errorhandler(MyDecoratorException) def my_decorator_exception_handler(e): - self.assert_true(isinstance(e, MyDecoratorException)) + assert isinstance(e, MyDecoratorException) return 'boom' def my_function_exception_handler(e): - self.assert_true(isinstance(e, MyFunctionException)) + assert isinstance(e, MyFunctionException) return 'bam' blue.register_error_handler(MyFunctionException, my_function_exception_handler) @@ -89,8 +91,8 @@ class TestBlueprint(TestFlask): c = app.test_client() - self.assert_equal(c.get('/decorator').data, b'boom') - self.assert_equal(c.get('/function').data, b'bam') + assert c.get('/decorator').data == b'boom' + assert c.get('/function').data == b'bam' def test_blueprint_url_definitions(self): bp = flask.Blueprint('test', __name__) @@ -108,10 +110,10 @@ class TestBlueprint(TestFlask): app.register_blueprint(bp, url_prefix='/2', url_defaults={'bar': 19}) c = app.test_client() - self.assert_equal(c.get('/1/foo').data, b'23/42') - self.assert_equal(c.get('/2/foo').data, b'19/42') - self.assert_equal(c.get('/1/bar').data, b'23') - self.assert_equal(c.get('/2/bar').data, b'19') + assert c.get('/1/foo').data == b'23/42' + assert c.get('/2/foo').data == b'19/42' + assert c.get('/1/bar').data == b'23' + assert c.get('/2/bar').data == b'19' def test_blueprint_url_processors(self): bp = flask.Blueprint('frontend', __name__, url_prefix='/') @@ -137,24 +139,24 @@ class TestBlueprint(TestFlask): c = app.test_client() - self.assert_equal(c.get('/de/').data, b'/de/about') - self.assert_equal(c.get('/de/about').data, b'/de/') + assert c.get('/de/').data == b'/de/about' + assert c.get('/de/about').data == b'/de/' def test_templates_and_static(self): from blueprintapp import app c = app.test_client() rv = c.get('/') - self.assert_equal(rv.data, b'Hello from the Frontend') + assert rv.data == b'Hello from the Frontend' rv = c.get('/admin/') - self.assert_equal(rv.data, b'Hello from the Admin') + assert rv.data == b'Hello from the Admin' rv = c.get('/admin/index2') - self.assert_equal(rv.data, b'Hello from the Admin') + assert rv.data == b'Hello from the Admin' rv = c.get('/admin/static/test.txt') - self.assert_equal(rv.data.strip(), b'Admin File') + assert rv.data.strip() == b'Admin File' rv.close() rv = c.get('/admin/static/css/test.css') - self.assert_equal(rv.data.strip(), b'/* nested file */') + assert rv.data.strip() == b'/* nested file */' rv.close() # try/finally, in case other tests use this app for Blueprint tests. @@ -166,25 +168,24 @@ class TestBlueprint(TestFlask): app.config['SEND_FILE_MAX_AGE_DEFAULT'] = expected_max_age rv = c.get('/admin/static/css/test.css') cc = parse_cache_control_header(rv.headers['Cache-Control']) - self.assert_equal(cc.max_age, expected_max_age) + assert cc.max_age == expected_max_age rv.close() finally: app.config['SEND_FILE_MAX_AGE_DEFAULT'] = max_age_default with app.test_request_context(): - self.assert_equal(flask.url_for('admin.static', filename='test.txt'), - '/admin/static/test.txt') + assert flask.url_for('admin.static', filename='test.txt') == '/admin/static/test.txt' with app.test_request_context(): try: flask.render_template('missing.html') except TemplateNotFound as e: - self.assert_equal(e.name, 'missing.html') + assert e.name == 'missing.html' else: - self.assert_true(0, 'expected exception') + assert 0, 'expected exception' with flask.Flask(__name__).test_request_context(): - self.assert_equal(flask.render_template('nested/nested.txt'), 'I\'m nested') + assert flask.render_template('nested/nested.txt') == 'I\'m nested' def test_default_static_cache_timeout(self): app = flask.Flask(__name__) @@ -205,7 +206,7 @@ class TestBlueprint(TestFlask): app.config['SEND_FILE_MAX_AGE_DEFAULT'] = unexpected_max_age rv = blueprint.send_static_file('index.html') cc = parse_cache_control_header(rv.headers['Cache-Control']) - self.assert_equal(cc.max_age, 100) + assert cc.max_age == 100 rv.close() finally: app.config['SEND_FILE_MAX_AGE_DEFAULT'] = max_age_default @@ -213,8 +214,7 @@ class TestBlueprint(TestFlask): def test_templates_list(self): from blueprintapp import app templates = sorted(app.jinja_env.list_templates()) - self.assert_equal(templates, ['admin/index.html', - 'frontend/index.html']) + assert templates == ['admin/index.html', 'frontend/index.html'] def test_dotted_names(self): frontend = flask.Blueprint('myapp.frontend', __name__) @@ -237,9 +237,9 @@ class TestBlueprint(TestFlask): app.register_blueprint(backend) c = app.test_client() - self.assert_equal(c.get('/fe').data.strip(), b'/be') - self.assert_equal(c.get('/fe2').data.strip(), b'/fe') - self.assert_equal(c.get('/be').data.strip(), b'/fe') + assert c.get('/fe').data.strip() == b'/be' + assert c.get('/fe2').data.strip() == b'/fe' + assert c.get('/be').data.strip() == b'/fe' def test_dotted_names_from_app(self): app = flask.Flask(__name__) @@ -258,7 +258,7 @@ class TestBlueprint(TestFlask): with app.test_client() as c: rv = c.get('/') - self.assert_equal(rv.data, b'/test/') + assert rv.data == b'/test/' def test_empty_url_defaults(self): bp = flask.Blueprint('bp', __name__) @@ -272,8 +272,8 @@ class TestBlueprint(TestFlask): app.register_blueprint(bp) c = app.test_client() - self.assert_equal(c.get('/').data, b'1') - self.assert_equal(c.get('/page/2').data, b'2') + assert c.get('/').data == b'1' + assert c.get('/page/2').data == b'2' def test_route_decorator_custom_endpoint(self): @@ -303,11 +303,11 @@ class TestBlueprint(TestFlask): return flask.request.endpoint c = app.test_client() - self.assert_equal(c.get('/').data, b'index') - self.assert_equal(c.get('/py/foo').data, b'bp.foo') - self.assert_equal(c.get('/py/bar').data, b'bp.bar') - self.assert_equal(c.get('/py/bar/123').data, b'bp.123') - self.assert_equal(c.get('/py/bar/foo').data, b'bp.bar_foo') + assert c.get('/').data == b'index' + assert c.get('/py/foo').data == b'bp.foo' + assert c.get('/py/bar').data == b'bp.bar' + assert c.get('/py/bar/123').data == b'bp.123' + assert c.get('/py/bar/foo').data == b'bp.bar_foo' def test_route_decorator_custom_endpoint_with_dots(self): bp = flask.Blueprint('bp', __name__) @@ -337,14 +337,14 @@ class TestBlueprint(TestFlask): def foo_foo_foo(): pass - self.assert_raises( + pytest.raises( AssertionError, lambda: bp.add_url_rule( '/bar/123', endpoint='bar.123', view_func=foo_foo_foo ) ) - self.assert_raises( + pytest.raises( AssertionError, bp.route('/bar/123', endpoint='bar.123'), lambda: None @@ -354,7 +354,7 @@ class TestBlueprint(TestFlask): app.register_blueprint(bp, url_prefix='/py') c = app.test_client() - self.assert_equal(c.get('/py/foo').data, b'bp.foo') + assert c.get('/py/foo').data == b'bp.foo' # The rule's didn't actually made it through rv = c.get('/py/bar') assert rv.status_code == 404 @@ -368,9 +368,9 @@ class TestBlueprint(TestFlask): return s[::-1] app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('my_reverse', app.jinja_env.filters.keys()) - self.assert_equal(app.jinja_env.filters['my_reverse'], my_reverse) - self.assert_equal(app.jinja_env.filters['my_reverse']('abcd'), 'dcba') + assert 'my_reverse' in app.jinja_env.filters.keys() + assert app.jinja_env.filters['my_reverse'] == my_reverse + assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba' def test_add_template_filter(self): bp = flask.Blueprint('bp', __name__) @@ -379,9 +379,9 @@ class TestBlueprint(TestFlask): bp.add_app_template_filter(my_reverse) app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('my_reverse', app.jinja_env.filters.keys()) - self.assert_equal(app.jinja_env.filters['my_reverse'], my_reverse) - self.assert_equal(app.jinja_env.filters['my_reverse']('abcd'), 'dcba') + assert 'my_reverse' in app.jinja_env.filters.keys() + assert app.jinja_env.filters['my_reverse'] == my_reverse + assert app.jinja_env.filters['my_reverse']('abcd') == 'dcba' def test_template_filter_with_name(self): bp = flask.Blueprint('bp', __name__) @@ -390,9 +390,9 @@ class TestBlueprint(TestFlask): return s[::-1] app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('strrev', app.jinja_env.filters.keys()) - self.assert_equal(app.jinja_env.filters['strrev'], my_reverse) - self.assert_equal(app.jinja_env.filters['strrev']('abcd'), 'dcba') + assert 'strrev' in app.jinja_env.filters.keys() + assert app.jinja_env.filters['strrev'] == my_reverse + assert app.jinja_env.filters['strrev']('abcd') == 'dcba' def test_add_template_filter_with_name(self): bp = flask.Blueprint('bp', __name__) @@ -401,9 +401,9 @@ class TestBlueprint(TestFlask): bp.add_app_template_filter(my_reverse, 'strrev') app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('strrev', app.jinja_env.filters.keys()) - self.assert_equal(app.jinja_env.filters['strrev'], my_reverse) - self.assert_equal(app.jinja_env.filters['strrev']('abcd'), 'dcba') + assert 'strrev' in app.jinja_env.filters.keys() + assert app.jinja_env.filters['strrev'] == my_reverse + assert app.jinja_env.filters['strrev']('abcd') == 'dcba' def test_template_filter_with_template(self): bp = flask.Blueprint('bp', __name__) @@ -416,7 +416,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_filter.html', value='abcd') rv = app.test_client().get('/') - self.assert_equal(rv.data, b'dcba') + assert rv.data == b'dcba' def test_template_filter_after_route_with_template(self): app = flask.Flask(__name__) @@ -429,7 +429,7 @@ class TestBlueprint(TestFlask): return s[::-1] app.register_blueprint(bp, url_prefix='/py') rv = app.test_client().get('/') - self.assert_equal(rv.data, b'dcba') + assert rv.data == b'dcba' def test_add_template_filter_with_template(self): bp = flask.Blueprint('bp', __name__) @@ -442,7 +442,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_filter.html', value='abcd') rv = app.test_client().get('/') - self.assert_equal(rv.data, b'dcba') + assert rv.data == b'dcba' def test_template_filter_with_name_and_template(self): bp = flask.Blueprint('bp', __name__) @@ -455,7 +455,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_filter.html', value='abcd') rv = app.test_client().get('/') - self.assert_equal(rv.data, b'dcba') + assert rv.data == b'dcba' def test_add_template_filter_with_name_and_template(self): bp = flask.Blueprint('bp', __name__) @@ -468,7 +468,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_filter.html', value='abcd') rv = app.test_client().get('/') - self.assert_equal(rv.data, b'dcba') + assert rv.data == b'dcba' def test_template_test(self): bp = flask.Blueprint('bp', __name__) @@ -477,9 +477,9 @@ class TestBlueprint(TestFlask): return isinstance(value, bool) app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('is_boolean', app.jinja_env.tests.keys()) - self.assert_equal(app.jinja_env.tests['is_boolean'], is_boolean) - self.assert_true(app.jinja_env.tests['is_boolean'](False)) + assert 'is_boolean' in app.jinja_env.tests.keys() + assert app.jinja_env.tests['is_boolean'] == is_boolean + assert app.jinja_env.tests['is_boolean'](False) def test_add_template_test(self): bp = flask.Blueprint('bp', __name__) @@ -488,9 +488,9 @@ class TestBlueprint(TestFlask): bp.add_app_template_test(is_boolean) app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('is_boolean', app.jinja_env.tests.keys()) - self.assert_equal(app.jinja_env.tests['is_boolean'], is_boolean) - self.assert_true(app.jinja_env.tests['is_boolean'](False)) + assert 'is_boolean' in app.jinja_env.tests.keys() + assert app.jinja_env.tests['is_boolean'] == is_boolean + assert app.jinja_env.tests['is_boolean'](False) def test_template_test_with_name(self): bp = flask.Blueprint('bp', __name__) @@ -499,9 +499,9 @@ class TestBlueprint(TestFlask): return isinstance(value, bool) app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('boolean', app.jinja_env.tests.keys()) - self.assert_equal(app.jinja_env.tests['boolean'], is_boolean) - self.assert_true(app.jinja_env.tests['boolean'](False)) + assert 'boolean' in app.jinja_env.tests.keys() + assert app.jinja_env.tests['boolean'] == is_boolean + assert app.jinja_env.tests['boolean'](False) def test_add_template_test_with_name(self): bp = flask.Blueprint('bp', __name__) @@ -510,9 +510,9 @@ class TestBlueprint(TestFlask): bp.add_app_template_test(is_boolean, 'boolean') app = flask.Flask(__name__) app.register_blueprint(bp, url_prefix='/py') - self.assert_in('boolean', app.jinja_env.tests.keys()) - self.assert_equal(app.jinja_env.tests['boolean'], is_boolean) - self.assert_true(app.jinja_env.tests['boolean'](False)) + assert 'boolean' in app.jinja_env.tests.keys() + assert app.jinja_env.tests['boolean'] == is_boolean + assert app.jinja_env.tests['boolean'](False) def test_template_test_with_template(self): bp = flask.Blueprint('bp', __name__) @@ -525,7 +525,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_test.html', value=False) rv = app.test_client().get('/') - self.assert_in(b'Success!', rv.data) + assert b'Success!' in rv.data def test_template_test_after_route_with_template(self): app = flask.Flask(__name__) @@ -538,7 +538,7 @@ class TestBlueprint(TestFlask): return isinstance(value, bool) app.register_blueprint(bp, url_prefix='/py') rv = app.test_client().get('/') - self.assert_in(b'Success!', rv.data) + assert b'Success!' in rv.data def test_add_template_test_with_template(self): bp = flask.Blueprint('bp', __name__) @@ -551,7 +551,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_test.html', value=False) rv = app.test_client().get('/') - self.assert_in(b'Success!', rv.data) + assert b'Success!' in rv.data def test_template_test_with_name_and_template(self): bp = flask.Blueprint('bp', __name__) @@ -564,7 +564,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_test.html', value=False) rv = app.test_client().get('/') - self.assert_in(b'Success!', rv.data) + assert b'Success!' in rv.data def test_add_template_test_with_name_and_template(self): bp = flask.Blueprint('bp', __name__) @@ -577,7 +577,7 @@ class TestBlueprint(TestFlask): def index(): return flask.render_template('template_test.html', value=False) rv = app.test_client().get('/') - self.assert_in(b'Success!', rv.data) + assert b'Success!' in rv.data def suite(): suite = unittest.TestSuite() diff --git a/tests/test_config.py b/tests/test_config.py index a0e5fb53..2faaa0c8 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -30,9 +30,9 @@ SECRET_KEY = 'devkey' class TestConfig(TestFlask): def common_object_test(self, app): - self.assert_equal(app.secret_key, 'devkey') - self.assert_equal(app.config['TEST_KEY'], 'foo') - self.assert_not_in('TestConfig', app.config) + assert app.secret_key == 'devkey' + assert app.config['TEST_KEY'] == 'foo' + assert 'TestConfig' not in app.config def test_config_from_file(self): app = flask.Flask(__name__) @@ -73,7 +73,7 @@ class TestConfig(TestFlask): self.common_object_test(app) app = flask.Flask(__name__) - with self.assert_raises(TypeError): + with pytest.raises(TypeError): app.config.from_mapping( {}, {} ) @@ -95,13 +95,13 @@ class TestConfig(TestFlask): try: app.config.from_envvar('FOO_SETTINGS') except RuntimeError as e: - self.assert_true("'FOO_SETTINGS' is not set" in str(e)) + assert "'FOO_SETTINGS' is not set" in str(e) else: - self.assert_true(0, 'expected exception') - self.assert_false(app.config.from_envvar('FOO_SETTINGS', silent=True)) + assert 0, 'expected exception' + assert not app.config.from_envvar('FOO_SETTINGS', silent=True) os.environ = {'FOO_SETTINGS': __file__.rsplit('.', 1)[0] + '.py'} - self.assert_true(app.config.from_envvar('FOO_SETTINGS')) + assert app.config.from_envvar('FOO_SETTINGS') self.common_object_test(app) finally: os.environ = env @@ -115,12 +115,12 @@ class TestConfig(TestFlask): app.config.from_envvar('FOO_SETTINGS') except IOError as e: msg = str(e) - self.assert_true(msg.startswith('[Errno 2] Unable to load configuration ' - 'file (No such file or directory):')) - self.assert_true(msg.endswith("missing.cfg'")) + assert msg.startswith('[Errno 2] Unable to load configuration ' + 'file (No such file or directory):') + assert msg.endswith("missing.cfg'") else: - self.fail('expected IOError') - self.assert_false(app.config.from_envvar('FOO_SETTINGS', silent=True)) + assert False, 'expected IOError' + assert not app.config.from_envvar('FOO_SETTINGS', silent=True) finally: os.environ = env @@ -130,12 +130,12 @@ class TestConfig(TestFlask): app.config.from_pyfile('missing.cfg') except IOError as e: msg = str(e) - self.assert_true(msg.startswith('[Errno 2] Unable to load configuration ' - 'file (No such file or directory):')) - self.assert_true(msg.endswith("missing.cfg'")) + assert msg.startswith('[Errno 2] Unable to load configuration ' + 'file (No such file or directory):') + assert msg.endswith("missing.cfg'") else: - self.assert_true(0, 'expected config') - self.assert_false(app.config.from_pyfile('missing.cfg', silent=True)) + assert 0, 'expected config' + assert not app.config.from_pyfile('missing.cfg', silent=True) def test_config_missing_json(self): app = flask.Flask(__name__) @@ -143,12 +143,12 @@ class TestConfig(TestFlask): app.config.from_json('missing.json') except IOError as e: msg = str(e) - self.assert_true(msg.startswith('[Errno 2] Unable to load configuration ' - 'file (No such file or directory):')) - self.assert_true(msg.endswith("missing.json'")) + assert msg.startswith('[Errno 2] Unable to load configuration ' + 'file (No such file or directory):') + assert msg.endswith("missing.json'") else: - self.assert_true(0, 'expected config') - self.assert_false(app.config.from_json('missing.json', silent=True)) + assert 0, 'expected config' + assert not app.config.from_json('missing.json', silent=True) def test_custom_config_class(self): class Config(flask.Config): @@ -156,14 +156,14 @@ class TestConfig(TestFlask): class Flask(flask.Flask): config_class = Config app = Flask(__name__) - self.assert_isinstance(app.config, Config) + assert isinstance(app.config, Config) app.config.from_object(__name__) self.common_object_test(app) def test_session_lifetime(self): app = flask.Flask(__name__) app.config['PERMANENT_SESSION_LIFETIME'] = 42 - self.assert_equal(app.permanent_session_lifetime.seconds, 42) + assert app.permanent_session_lifetime.seconds == 42 def test_get_namespace(self): app = flask.Flask(__name__) @@ -172,13 +172,13 @@ class TestConfig(TestFlask): app.config['BAR_STUFF_1'] = 'bar stuff 1' app.config['BAR_STUFF_2'] = 'bar stuff 2' foo_options = app.config.get_namespace('FOO_') - self.assert_equal(2, len(foo_options)) - self.assert_equal('foo option 1', foo_options['option_1']) - self.assert_equal('foo option 2', foo_options['option_2']) + assert 2 == len(foo_options) + assert 'foo option 1' == foo_options['option_1'] + assert 'foo option 2' == foo_options['option_2'] bar_options = app.config.get_namespace('BAR_', lowercase=False) - self.assert_equal(2, len(bar_options)) - self.assert_equal('bar stuff 1', bar_options['STUFF_1']) - self.assert_equal('bar stuff 2', bar_options['STUFF_2']) + assert 2 == len(bar_options) + assert 'bar stuff 1' == bar_options['STUFF_1'] + assert 'bar stuff 2' == bar_options['STUFF_2'] class TestInstance(TestFlask): @@ -188,7 +188,7 @@ class TestInstance(TestFlask): assert 'must be absolute' in str(excinfo.value) app = flask.Flask(__name__, instance_path=str(apps_tmpdir)) - self.assert_equal(app.instance_path, str(apps_tmpdir)) + assert app.instance_path == str(apps_tmpdir) def test_main_module_paths(self, apps_tmpdir, purge_module): app = apps_tmpdir.join('main_app.py') @@ -285,7 +285,7 @@ class TestInstance(TestFlask): return self sys.meta_path.append(Loader()) try: - with self.assert_raises(AttributeError): + with pytest.raises(AttributeError): flask.Flask(__name__) finally: sys.meta_path.pop() diff --git a/tests/test_ext.py b/tests/test_ext.py index e48563bf..1bec1b62 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -11,6 +11,8 @@ import sys import unittest +import pytest + try: from imp import reload as reload_module except ImportError: @@ -41,70 +43,70 @@ class TestExtImportHook(TestFlask): if cls.__module__ == 'flask.exthook' and \ cls.__name__ == 'ExtensionImporter': import_hooks += 1 - self.assert_equal(import_hooks, 1) + assert import_hooks == 1 def teardown(self): from flask import ext for key in ext.__dict__: - self.assert_not_in('.', key) + assert '.' not in key def test_flaskext_new_simple_import_normal(self): from flask.ext.newext_simple import ext_id - self.assert_equal(ext_id, 'newext_simple') + assert ext_id == 'newext_simple' def test_flaskext_new_simple_import_module(self): from flask.ext import newext_simple - self.assert_equal(newext_simple.ext_id, 'newext_simple') - self.assert_equal(newext_simple.__name__, 'flask_newext_simple') + assert newext_simple.ext_id == 'newext_simple' + assert newext_simple.__name__ == 'flask_newext_simple' def test_flaskext_new_package_import_normal(self): from flask.ext.newext_package import ext_id - self.assert_equal(ext_id, 'newext_package') + assert ext_id == 'newext_package' def test_flaskext_new_package_import_module(self): from flask.ext import newext_package - self.assert_equal(newext_package.ext_id, 'newext_package') - self.assert_equal(newext_package.__name__, 'flask_newext_package') + assert newext_package.ext_id == 'newext_package' + assert newext_package.__name__ == 'flask_newext_package' def test_flaskext_new_package_import_submodule_function(self): from flask.ext.newext_package.submodule import test_function - self.assert_equal(test_function(), 42) + assert test_function() == 42 def test_flaskext_new_package_import_submodule(self): from flask.ext.newext_package import submodule - self.assert_equal(submodule.__name__, 'flask_newext_package.submodule') - self.assert_equal(submodule.test_function(), 42) + assert submodule.__name__ == 'flask_newext_package.submodule' + assert submodule.test_function() == 42 def test_flaskext_old_simple_import_normal(self): from flask.ext.oldext_simple import ext_id - self.assert_equal(ext_id, 'oldext_simple') + assert ext_id == 'oldext_simple' def test_flaskext_old_simple_import_module(self): from flask.ext import oldext_simple - self.assert_equal(oldext_simple.ext_id, 'oldext_simple') - self.assert_equal(oldext_simple.__name__, 'flaskext.oldext_simple') + assert oldext_simple.ext_id == 'oldext_simple' + assert oldext_simple.__name__ == 'flaskext.oldext_simple' def test_flaskext_old_package_import_normal(self): from flask.ext.oldext_package import ext_id - self.assert_equal(ext_id, 'oldext_package') + assert ext_id == 'oldext_package' def test_flaskext_old_package_import_module(self): from flask.ext import oldext_package - self.assert_equal(oldext_package.ext_id, 'oldext_package') - self.assert_equal(oldext_package.__name__, 'flaskext.oldext_package') + assert oldext_package.ext_id == 'oldext_package' + assert oldext_package.__name__ == 'flaskext.oldext_package' def test_flaskext_old_package_import_submodule(self): from flask.ext.oldext_package import submodule - self.assert_equal(submodule.__name__, 'flaskext.oldext_package.submodule') - self.assert_equal(submodule.test_function(), 42) + assert submodule.__name__ == 'flaskext.oldext_package.submodule' + assert submodule.test_function() == 42 def test_flaskext_old_package_import_submodule_function(self): from flask.ext.oldext_package.submodule import test_function - self.assert_equal(test_function(), 42) + assert test_function() == 42 def test_flaskext_broken_package_no_module_caching(self): for x in range(2): - with self.assert_raises(ImportError): + with pytest.raises(ImportError): import flask.ext.broken def test_no_error_swallowing(self): @@ -112,13 +114,13 @@ class TestExtImportHook(TestFlask): import flask.ext.broken except ImportError: exc_type, exc_value, tb = sys.exc_info() - self.assert_true(exc_type is ImportError) + assert exc_type is ImportError if PY2: message = 'No module named missing_module' else: message = 'No module named \'missing_module\'' - self.assert_equal(str(exc_value), message) - self.assert_true(tb.tb_frame.f_globals is globals()) + assert str(exc_value) == message + assert tb.tb_frame.f_globals is globals() # reraise() adds a second frame so we need to skip that one too. # On PY3 we even have another one :( @@ -127,7 +129,8 @@ class TestExtImportHook(TestFlask): next = next.tb_next import os.path - self.assert_in(os.path.join('flask_broken', '__init__.py'), next.tb_frame.f_code.co_filename) + assert os.path.join('flask_broken', '__init__.py') in \ + next.tb_frame.f_code.co_filename def suite(): diff --git a/tests/test_helpers.py b/tests/test_helpers.py index e5055fa6..d1091729 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -9,6 +9,8 @@ :license: BSD, see LICENSE for more details. """ +import pytest + import os import flask import unittest @@ -36,7 +38,7 @@ class TestJSON(TestFlask): return flask.jsonify(foo=text_type(flask.request.get_json())) c = app.test_client() rv = c.post('/json', data='malformed', content_type='application/json') - self.assert_equal(rv.status_code, 400) + assert rv.status_code == 400 def test_json_custom_mimetypes(self): app = flask.Flask(__name__) @@ -45,7 +47,7 @@ class TestJSON(TestFlask): return flask.request.get_json() c = app.test_client() rv = c.post('/json', data='"foo"', content_type='application/x+json') - self.assert_equal(rv.data, b'foo') + assert rv.data == b'foo' def test_json_body_encoding(self): app = flask.Flask(__name__) @@ -57,7 +59,7 @@ class TestJSON(TestFlask): c = app.test_client() resp = c.get('/', data=u'"Hällo Wörld"'.encode('iso-8859-15'), content_type='application/json; charset=iso-8859-15') - self.assert_equal(resp.data, u'Hällo Wörld'.encode('utf-8')) + assert resp.data == u'Hällo Wörld'.encode('utf-8') def test_jsonify(self): d = dict(a=23, b=42, c=[1, 2, 3]) @@ -71,8 +73,8 @@ class TestJSON(TestFlask): c = app.test_client() for url in '/kw', '/dict': rv = c.get(url) - self.assert_equal(rv.mimetype, 'application/json') - self.assert_equal(flask.json.loads(rv.data), d) + assert rv.mimetype == 'application/json' + assert flask.json.loads(rv.data) == d def test_json_as_unicode(self): app = flask.Flask(__name__) @@ -80,12 +82,12 @@ class TestJSON(TestFlask): app.config['JSON_AS_ASCII'] = True with app.app_context(): rv = flask.json.dumps(u'\N{SNOWMAN}') - self.assert_equal(rv, '"\\u2603"') + assert rv == '"\\u2603"' app.config['JSON_AS_ASCII'] = False with app.app_context(): rv = flask.json.dumps(u'\N{SNOWMAN}') - self.assert_equal(rv, u'"\u2603"') + assert rv == u'"\u2603"' def test_json_attr(self): app = flask.Flask(__name__) @@ -96,29 +98,28 @@ class TestJSON(TestFlask): c = app.test_client() rv = c.post('/add', data=flask.json.dumps({'a': 1, 'b': 2}), content_type='application/json') - self.assert_equal(rv.data, b'3') + assert rv.data == b'3' def test_template_escaping(self): app = flask.Flask(__name__) render = flask.render_template_string with app.test_request_context(): rv = flask.json.htmlsafe_dumps('') - self.assert_equal(rv, u'"\\u003c/script\\u003e"') - self.assert_equal(type(rv), text_type) + assert rv == u'"\\u003c/script\\u003e"' + assert type(rv) == text_type rv = render('{{ ""|tojson }}') - self.assert_equal(rv, '"\\u003c/script\\u003e"') + assert rv == '"\\u003c/script\\u003e"' rv = render('{{ "<\0/script>"|tojson }}') - self.assert_equal(rv, '"\\u003c\\u0000/script\\u003e"') + assert rv == '"\\u003c\\u0000/script\\u003e"' rv = render('{{ "