Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '1117-start-new-test-suite'
- Loading branch information
Showing
32 changed files
with
2,067 additions
and
286 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
''' | ||
Controller tests probably shouldn't use mocking. | ||
.. todo:: | ||
Write the tests for one controller, figuring out the best way to write | ||
controller tests. Then fill in this guidelines section, using the first set | ||
of controller tests as an example. | ||
Some things have been decided already: | ||
* All controller methods should have tests | ||
* Controller tests should be high-level tests that work by posting simulated | ||
HTTP requests to CKAN URLs and testing the response. So the controller | ||
tests are also testing CKAN's templates and rendering - these are CKAN's | ||
front-end tests. | ||
For example, maybe we use a webtests testapp and then use beautiful soup | ||
to parse the HTML? | ||
* In general the tests for a controller shouldn't need to be too detailed, | ||
because there shouldn't be a lot of complicated logic and code in | ||
controller classes. The logic should be handled in other places such as | ||
:mod:`ckan.logic` and :mod:`ckan.lib`, where it can be tested easily and | ||
also shared with other code. | ||
* The tests for a controller should: | ||
* Make sure that the template renders without crashing. | ||
* Test that the page contents seem basically correct, or test certain | ||
important elements in the page contents (but don't do too much HTML | ||
parsing). | ||
* Test that submitting any forms on the page works without crashing and | ||
has the expected side-effects. | ||
* When asserting side-effects after submitting a form, controller tests | ||
should user the :func:`ckan.new_tests.helpers.call_action` function. For | ||
example after creating a new user by submitting the new user form, a | ||
test could call the :func:`~ckan.logic.action.get.user_show` action | ||
function to verify that the user was created with the correct values. | ||
.. warning:: | ||
Some CKAN controllers *do* contain a lot of complicated logic code. These | ||
controllers should be refactored to move the logic into :mod:`ckan.logic` or | ||
:mod:`ckan.lib` where it can be tested easily. Unfortunately in cases like | ||
this it may be necessary to write a lot of controller tests to get this | ||
code's behavior into a test harness before it can be safely refactored. | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
'''This is a collection of factory classes for building CKAN users, datasets, | ||
etc. | ||
These are meant to be used by tests to create any objects that are needed for | ||
the tests. They're written using ``factory_boy``: | ||
http://factoryboy.readthedocs.org/en/latest/ | ||
These are not meant to be used for the actual testing, e.g. if you're writing a | ||
test for the :py:func:`~ckan.logic.action.create.user_create` function then | ||
call :py:func:`~ckan.new_tests.helpers.call_action`, don't test it | ||
via the :py:class:`~ckan.new_tests.factories.User` factory below. | ||
Usage:: | ||
# Create a user with the factory's default attributes, and get back a | ||
# user dict: | ||
user_dict = factories.User() | ||
# You can create a second user the same way. For attributes that can't be | ||
# the same (e.g. you can't have two users with the same name) a new value | ||
# will be generated each time you use the factory: | ||
another_user_dict = factories.User() | ||
# Create a user and specify your own user name and email (this works | ||
# with any params that CKAN's user_create() accepts): | ||
custom_user_dict = factories.User(name='bob', email='bob@bob.com') | ||
# Get a user dict containing the attributes (name, email, password, etc.) | ||
# that the factory would use to create a user, but without actually | ||
# creating the user in CKAN: | ||
user_attributes_dict = factories.User.attributes() | ||
# If you later want to create a user using these attributes, just pass them | ||
# to the factory: | ||
user = factories.User(**user_attributes_dict) | ||
''' | ||
import factory | ||
import mock | ||
|
||
import ckan.model | ||
import ckan.logic | ||
import ckan.new_tests.helpers as helpers | ||
|
||
|
||
def _generate_email(user): | ||
'''Return an email address for the given User factory stub object.''' | ||
|
||
return '{0}@ckan.org'.format(user.name).lower() | ||
|
||
|
||
def _generate_reset_key(user): | ||
'''Return a reset key for the given User factory stub object.''' | ||
|
||
return '{0}_reset_key'.format(user.name).lower() | ||
|
||
|
||
def _generate_user_id(user): | ||
'''Return a user id for the given User factory stub object.''' | ||
|
||
return '{0}_user_id'.format(user.name).lower() | ||
|
||
|
||
class User(factory.Factory): | ||
'''A factory class for creating CKAN users.''' | ||
|
||
# This is the class that UserFactory will create and return instances | ||
# of. | ||
FACTORY_FOR = ckan.model.User | ||
|
||
# These are the default params that will be used to create new users. | ||
fullname = 'Mr. Test User' | ||
password = 'pass' | ||
about = 'Just another test user.' | ||
|
||
# Generate a different user name param for each user that gets created. | ||
name = factory.Sequence(lambda n: 'test_user_{n}'.format(n=n)) | ||
|
||
# Compute the email param for each user based on the values of the other | ||
# params above. | ||
email = factory.LazyAttribute(_generate_email) | ||
|
||
# I'm not sure how to support factory_boy's .build() feature in CKAN, | ||
# so I've disabled it here. | ||
@classmethod | ||
def _build(cls, target_class, *args, **kwargs): | ||
raise NotImplementedError(".build() isn't supported in CKAN") | ||
|
||
# To make factory_boy work with CKAN we override _create() and make it call | ||
# a CKAN action function. | ||
# We might also be able to do this by using factory_boy's direct SQLAlchemy | ||
# support: http://factoryboy.readthedocs.org/en/latest/orms.html#sqlalchemy | ||
@classmethod | ||
def _create(cls, target_class, *args, **kwargs): | ||
if args: | ||
assert False, "Positional args aren't supported, use keyword args." | ||
user_dict = helpers.call_action('user_create', **kwargs) | ||
return user_dict | ||
|
||
|
||
class MockUser(factory.Factory): | ||
'''A factory class for creating mock CKAN users using the mock library.''' | ||
|
||
FACTORY_FOR = mock.MagicMock | ||
|
||
fullname = 'Mr. Mock User' | ||
password = 'pass' | ||
about = 'Just another mock user.' | ||
name = factory.Sequence(lambda n: 'mock_user_{n}'.format(n=n)) | ||
email = factory.LazyAttribute(_generate_email) | ||
reset_key = factory.LazyAttribute(_generate_reset_key) | ||
id = factory.LazyAttribute(_generate_user_id) | ||
|
||
@classmethod | ||
def _build(cls, target_class, *args, **kwargs): | ||
raise NotImplementedError(".build() isn't supported in CKAN") | ||
|
||
@classmethod | ||
def _create(cls, target_class, *args, **kwargs): | ||
if args: | ||
assert False, "Positional args aren't supported, use keyword args." | ||
mock_user = mock.MagicMock() | ||
for name, value in kwargs.items(): | ||
setattr(mock_user, name, value) | ||
return mock_user | ||
|
||
|
||
def validator_data_dict(): | ||
'''Return a data dict with some arbitrary data in it, suitable to be passed | ||
to validator functions for testing. | ||
''' | ||
return {('other key',): 'other value'} | ||
|
||
|
||
def validator_errors_dict(): | ||
'''Return an errors dict with some arbitrary errors in it, suitable to be | ||
passed to validator functions for testing. | ||
''' | ||
return {('other key',): ['other error']} |
Oops, something went wrong.