summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Piercy <web@stevepiercy.com>2020-01-08 02:00:20 -0800
committerSteve Piercy <web@stevepiercy.com>2020-01-08 02:00:20 -0800
commit3630b1ebd981a994b83689a6becb9922f1b20f0a (patch)
tree7fe2c695957730bc5251b70761ea3c54c5667b9d
parent14403a3f6d7cb870aefafa6bfa8999f86aa29c86 (diff)
downloadpyramid-3630b1ebd981a994b83689a6becb9922f1b20f0a.tar.gz
pyramid-3630b1ebd981a994b83689a6becb9922f1b20f0a.tar.bz2
pyramid-3630b1ebd981a994b83689a6becb9922f1b20f0a.zip
sync cookiecutter to starter project `myproject`
-rw-r--r--docs/narr/myproject/.gitignore1
-rw-r--r--docs/narr/myproject/testing.ini53
-rw-r--r--docs/narr/myproject/tests/conftest.py69
-rw-r--r--docs/narr/myproject/tests/test_functional.py7
-rw-r--r--docs/narr/myproject/tests/test_it.py39
-rw-r--r--docs/narr/myproject/tests/test_views.py13
-rw-r--r--docs/narr/project.rst47
-rw-r--r--docs/narr/testing.rst23
8 files changed, 195 insertions, 57 deletions
diff --git a/docs/narr/myproject/.gitignore b/docs/narr/myproject/.gitignore
index 1853d983c..c612e59f2 100644
--- a/docs/narr/myproject/.gitignore
+++ b/docs/narr/myproject/.gitignore
@@ -19,3 +19,4 @@ Data.fs*
.DS_Store
coverage
test
+*.sqlite
diff --git a/docs/narr/myproject/testing.ini b/docs/narr/myproject/testing.ini
new file mode 100644
index 000000000..f2ef86805
--- /dev/null
+++ b/docs/narr/myproject/testing.ini
@@ -0,0 +1,53 @@
+###
+# app configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:myproject
+
+pyramid.reload_templates = false
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+listen = localhost:6543
+
+###
+# logging configuration
+# https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, myproject
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_myproject]
+level = DEBUG
+handlers =
+qualname = myproject
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/narr/myproject/tests/conftest.py b/docs/narr/myproject/tests/conftest.py
new file mode 100644
index 000000000..296205927
--- /dev/null
+++ b/docs/narr/myproject/tests/conftest.py
@@ -0,0 +1,69 @@
+import os
+from pyramid.paster import get_appsettings
+from pyramid.scripting import prepare
+from pyramid.testing import DummyRequest
+import pytest
+import webtest
+
+from myproject import main
+
+
+def pytest_addoption(parser):
+ parser.addoption('--ini', action='store', metavar='INI_FILE')
+
+@pytest.fixture(scope='session')
+def ini_file(request):
+ # potentially grab this path from a pytest option
+ return os.path.abspath(request.config.option.ini or 'testing.ini')
+
+@pytest.fixture(scope='session')
+def app_settings(ini_file):
+ return get_appsettings(ini_file)
+
+@pytest.fixture(scope='session')
+def app(app_settings):
+ return main({}, **app_settings)
+
+@pytest.fixture
+def testapp(app):
+ testapp = webtest.TestApp(app, extra_environ={
+ 'HTTP_HOST': 'example.com',
+ })
+
+ return testapp
+
+@pytest.fixture
+def app_request(app):
+ """
+ A real request.
+
+ This request is almost identical to a real request but it has some
+ drawbacks in tests as it's harder to mock data and is heavier.
+
+ """
+ env = prepare(registry=app.registry)
+ request = env['request']
+ request.host = 'example.com'
+
+ yield request
+ env['closer']()
+
+@pytest.fixture
+def dummy_request(app):
+ """
+ A lightweight dummy request.
+
+ This request is ultra-lightweight and should be used only when the
+ request itself is not a large focus in the call-stack.
+
+ It is way easier to mock and control side-effects using this object.
+
+ - It does not have request extensions applied.
+ - Threadlocals are not properly pushed.
+
+ """
+ request = DummyRequest()
+ request.registry = app.registry
+ request.host = 'example.com'
+
+ return request
diff --git a/docs/narr/myproject/tests/test_functional.py b/docs/narr/myproject/tests/test_functional.py
new file mode 100644
index 000000000..bac5d63f4
--- /dev/null
+++ b/docs/narr/myproject/tests/test_functional.py
@@ -0,0 +1,7 @@
+def test_root(testapp):
+ res = testapp.get('/', status=200)
+ assert b'Pyramid' in res.body
+
+def test_notfound(testapp):
+ res = testapp.get('/badurl', status=404)
+ assert res.status_code == 404
diff --git a/docs/narr/myproject/tests/test_it.py b/docs/narr/myproject/tests/test_it.py
deleted file mode 100644
index b300da34d..000000000
--- a/docs/narr/myproject/tests/test_it.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import unittest
-
-from pyramid import testing
-
-
-class ViewTests(unittest.TestCase):
- def setUp(self):
- self.config = testing.setUp()
-
- def tearDown(self):
- testing.tearDown()
-
- def test_my_view(self):
- from myproject.views.default import my_view
- request = testing.DummyRequest()
- info = my_view(request)
- self.assertEqual(info['project'], 'myproject')
-
- def test_notfound_view(self):
- from myproject.views.notfound import notfound_view
- request = testing.DummyRequest()
- info = notfound_view(request)
- self.assertEqual(info, {})
-
-
-class FunctionalTests(unittest.TestCase):
- def setUp(self):
- from myproject import main
- app = main({})
- from webtest import TestApp
- self.testapp = TestApp(app)
-
- def test_root(self):
- res = self.testapp.get('/', status=200)
- self.assertTrue(b'Pyramid' in res.body)
-
- def test_notfound(self):
- res = self.testapp.get('/badurl', status=404)
- self.assertTrue(res.status_code == 404)
diff --git a/docs/narr/myproject/tests/test_views.py b/docs/narr/myproject/tests/test_views.py
new file mode 100644
index 000000000..1fd9db8ab
--- /dev/null
+++ b/docs/narr/myproject/tests/test_views.py
@@ -0,0 +1,13 @@
+from myproject.views.default import my_view
+from myproject.views.notfound import notfound_view
+
+
+def test_my_view(app_request):
+ info = my_view(app_request)
+ assert app_request.response.status_int == 200
+ assert info['project'] == 'myproject'
+
+def test_notfound_view(app_request):
+ info = notfound_view(app_request)
+ assert app_request.response.status_int == 404
+ assert info == {}
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 043f77754..6493f0fe7 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -210,9 +210,9 @@ Elided output from a run of this command on Unix is shown below:
Running setup.py develop for myproject
Successfully installed Jinja2-2.10.3 Mako-1.1.0 MarkupSafe-1.1.1 \
PasteDeploy-2.0.1 Pygments-2.5.2 hupper-1.9.1 myproject plaster-1.0 \
- plaster-pastedeploy-0.7 pyramid-1.10.4 pyramid-debugtoolbar-4.5.1 \
+ plaster-pastedeploy-0.7 pyramid-1.10.4 pyramid-debugtoolbar-4.5.2 \
pyramid-jinja2-2.8 pyramid-mako-1.1.0 repoze.lru-0.7 \
- translationstring-1.3 venusian-3.0.0 waitress-1.4.1 webob-1.8.5 \
+ translationstring-1.3 venusian-3.0.0 waitress-1.4.2 webob-1.8.5 \
zope.deprecation-4.4.0 zope.interface-4.7.1
This will install a :term:`distribution` representing your project into the
@@ -264,9 +264,9 @@ Here's sample output from a test run on Unix:
$VENV/bin/pytest -q
....
- 4 passed in 0.45 seconds
+ 4 passed in 0.31s
-The tests themselves are found in the ``test_it.py`` module in the ``tests`` package in your ``cookiecutter``-generated project.
+The tests themselves are found in the ``tests`` package in your ``cookiecutter``-generated project.
Within this project generated by the ``pyramid-cookiecutter-starter`` cookiecutter, only a few sample tests exist.
.. note::
@@ -555,10 +555,12 @@ The ``myproject`` project we've generated has the following directory structure:
│   └── notfound.py
├── production.ini
├── pytest.ini
- ├── setup.py
+ ├── testing.ini
└── tests
├── __init__.py
- └── test_it.py
+ ├── conftest.py
+ ├── test_functional.py
+ └── test_views.py
.. index::
@@ -567,17 +569,27 @@ The ``myproject`` project we've generated has the following directory structure:
``test_it.py``
~~~~~~~~~~~~~~
-The ``test_it.py`` module in the ``tests`` package includes tests for your application.
+The ``conftest.py``, ``test_functional.py``, and ``test_views.py`` modules in the ``tests`` package includes tests for your application.
-.. literalinclude:: myproject/tests/test_it.py
+.. literalinclude:: myproject/tests/conftest.py
:language: python
:linenos:
-This sample ``test_it.py`` file has two unit tests and two functional tests defined within it.
+.. literalinclude:: myproject/tests/test_functional.py
+ :language: python
+ :linenos:
+
+.. literalinclude:: myproject/tests/test_views.py
+ :language: python
+ :linenos:
+
+The sample ``conftest.py`` file contains test configuration and fixtures.
+The sample ``test_functional.py`` file has two functional tests defined within it.
+The sample ``test_views.py`` file has two unit tests defined within it.
These tests are executed when you run ``pytest -q``.
You may add more tests here as you build your application.
You are not required to write tests to use :app:`Pyramid`.
-This file is simply provided for convenience and example.
+These files are provided only for convenience and example.
See :ref:`testing_chapter` for more information about writing :app:`Pyramid` unit tests.
@@ -615,6 +627,8 @@ describe, run, and test your application.
#. ``setup.py`` is the file you'll use to test and distribute your application.
It is a standard :term:`Setuptools` ``setup.py`` file.
+#. ``testing.ini`` is a :term:`PasteDeploy` configuration file that can be used to execute your application's tests.
+
#. ``tests`` package which contains unit and functional test code for the application.
.. index::
@@ -717,6 +731,19 @@ inclusion of this toolbar slows down page rendering times by over an order of
magnitude. The debug toolbar is also a potential security risk if you have it
configured incorrectly.
+
+.. index::
+ single: testing.ini
+
+``testing.ini``
+~~~~~~~~~~~~~~~
+
+The ``testing.ini`` file is a :term:`PasteDeploy` configuration file with a purpose much like that of ``development.ini``.
+It is similar to ``development.ini``, but is optimized to reduce test execution time.
+It disables the debug toolbar and automatic reloading of templates, as these slow down test execution.
+This file is appropriate to use instead of ``development.ini`` when you run your application's tests.
+
+
.. index::
single: MANIFEST.in
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 0fa1e98fd..bb23d5137 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -395,23 +395,30 @@ As always, whenever you change your dependencies, make sure to run the correct
$VENV/bin/pip install -e ".[testing]"
-In your ``MyPackage`` project, your :term:`package` is named ``myproject``
+In your ``myproject`` project, your :term:`package` is named ``myproject``
which contains a ``views`` package containing a ``default.py`` module, which in turn contains a :term:`view`
function ``my_view`` that returns an HTML body when the root URL is invoked:
- .. literalinclude:: myproject/myproject/views/default.py
- :linenos:
- :language: python
+ .. literalinclude:: myproject/myproject/views/default.py
+ :linenos:
+ :language: python
+
+Test configuration and fixtures are defined in ``conftest.py``.
+In the following example, we define a test fixture.
+
+ .. literalinclude:: myproject/tests/conftest.py
+ :pyobject: testapp
+ :linenos:
+ :language: python
-The following example functional tests demonstrate invoking the above :term:`view`:
+This fixture is used in the following example functional tests, to demonstrate invoking the above :term:`view`:
- .. literalinclude:: myproject/tests/test_it.py
+ .. literalinclude:: myproject/tests/test_functional.py
:linenos:
- :pyobject: FunctionalTests
:language: python
When these tests are run, each test method creates a "real" :term:`WSGI` application using the ``main`` function in your ``myproject.__init__`` module, using :term:`WebTest` to wrap that WSGI application.
-It assigns the result to ``self.testapp``.
+It assigns the result to ``res``.
In the test named ``test_root``, the ``TestApp``'s ``GET`` method is used to invoke the root URL.
An assertion is made that the returned HTML contains the text ``Pyramid``.