Skip to content

Commit

Permalink
Merge pull request #23 from IQSS/automated-tests
Browse files Browse the repository at this point in the history
Automated tests
  • Loading branch information
pdurbin committed May 22, 2015
2 parents ad72655 + f5f31f0 commit f84b980
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 42 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
.cache/
local.py
*~
*.egg-info/
*.egg-info/

12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
language: python
python:
- 2.6
- 2.7
- 3.3
#- 3.4 # "No output has been received in the last 10 minutes, this potentially indicates a stalled build or something wrong with the build itself."
install:
- pip install -U .
- pip install httpretty pytest flake8
script:
- flake8 .
- py.test
30 changes: 22 additions & 8 deletions dataverse/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ class Connection(object):
def __init__(self, host, token):
self.token = token
self.host = host
self.sd_uri = 'https://{host}/dvn/api/data-deposit/v1.1/swordv2/service-document'.format(host=self.host)

self.base_url = 'https://{0}'.format(self.host)
self.native_base_url = '{0}/api/v1'.format(self.base_url)
self.sword_base_url = '{0}/dvn/api/data-deposit/v1.1/swordv2'.format(self.base_url)
self.sd_uri = '{0}/service-document'.format(self.sword_base_url)
self._service_document = None

self.get_service_document()
Expand All @@ -38,7 +42,7 @@ def get_service_document(self, refresh=False):

def create_dataverse(self, alias, name, email, parent=':root'):
resp = requests.post(
'https://{0}/api/dataverses/{1}'.format(self.host, parent),
'{0}/dataverses/{1}'.format(self.native_base_url, parent),
json={
'alias': alias,
'name': name,
Expand All @@ -48,26 +52,36 @@ def create_dataverse(self, alias, name, email, parent=':root'):
)

if resp.status_code == 404:
raise exceptions.DataverseNotFoundError('Dataverse {0} was not found.'.format(parent))
raise exceptions.DataverseNotFoundError(
'Dataverse {0} was not found.'.format(parent)
)
elif resp.status_code != 201:
raise exceptions.OperationFailedError('{0} Dataverse could not be created.'.format(name))
raise exceptions.OperationFailedError(
'{0} Dataverse could not be created.'.format(name)
)

self.get_service_document(refresh=True)
return self.get_dataverse(alias)

def delete_dataverse(self, dataverse):

resp = requests.delete(
'https://{0}/api/dataverses/{1}'.format(self.host, dataverse.alias),
'{0}/dataverses/{1}'.format(self.native_base_url, dataverse.alias),
params={'key': self.token},
)

if resp.status_code == 401:
raise exceptions.UnauthorizedError('Delete Dataverse unauthorized.')
raise exceptions.UnauthorizedError(
'Delete Dataverse {0} unauthorized.'.format(dataverse.alias)
)
elif resp.status_code == 404:
raise exceptions.DataverseNotFoundError('Dataverse {0} was not found.'.format(dataverse.alias))
raise exceptions.DataverseNotFoundError(
'Dataverse {0} was not found.'.format(dataverse.alias)
)
elif resp.status_code != 200:
raise exceptions.OperationFailedError('Dataverse {0} could not be deleted.'.format(dataverse.alias))
raise exceptions.OperationFailedError(
'Dataverse {0} could not be deleted.'.format(dataverse.alias)
)

self.get_service_document(refresh=True)

Expand Down
18 changes: 12 additions & 6 deletions dataverse/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,16 +185,18 @@ def get_metadata(self, version='latest', refresh=False):
if not self.dataverse:
raise NoContainerError('This dataset has not been added to a Dataverse.')

url = 'https://{0}/api/datasets/{1}/versions/:{2}'.format(
self.connection.host,
url = '{0}/datasets/{1}/versions/:{2}'.format(
self.connection.native_base_url,
self.id,
version,
)

resp = requests.get(url, params={'key': self.connection.token})

if resp.status_code == 404:
raise VersionJsonNotFoundError('JSON metadata could not be found for this version.')
raise VersionJsonNotFoundError(
'JSON metadata could not be found for this version.'
)
elif resp.status_code != 200:
raise ConnectionError('JSON metadata could not be retrieved.')

Expand All @@ -203,7 +205,11 @@ def get_metadata(self, version='latest', refresh=False):

# Update corresponding version metadata if retrieving 'latest'
if version == 'latest':
latest_version = 'latest-published' if metadata['versionState'] == 'RELEASED' else 'draft'
latest_version = (
'latest-published'
if metadata['versionState'] == 'RELEASED'
else 'draft'
)
self._metadata[latest_version] = metadata

return metadata
Expand All @@ -214,8 +220,8 @@ def update_metadata(self, metadata):
:param dict metadata: json retrieved from `get_version_metadata`
"""
url = 'https://{0}/api/datasets/{1}/versions/:draft'.format(
self.connection.host,
url = '{0}/datasets/{1}/versions/:draft'.format(
self.connection.native_base_url,
self.id,
)
resp = requests.put(
Expand Down
8 changes: 4 additions & 4 deletions dataverse/dataverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def get_contents(self, refresh=False):
if not refresh and self._contents_json:
return self._contents_json

content_uri = 'https://{0}/api/dataverses/{1}/contents'.format(
self.connection.host, self.alias
content_uri = '{0}/dataverses/{1}/contents'.format(
self.connection.native_base_url, self.alias
)
resp = requests.get(
content_uri,
Expand All @@ -76,8 +76,8 @@ def get_collection_info(self, refresh=False):
return self._collection_info

def publish(self):
edit_uri = 'https://{0}/dvn/api/data-deposit/v1.1/swordv2/edit/dataverse/{1}'.format(
self.connection.host, self.alias
edit_uri = '{0}/edit/dataverse/{1}'.format(
self.connection.sword_base_url, self.alias
)
resp = requests.post(
edit_uri,
Expand Down
1 change: 1 addition & 0 deletions dataverse/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import absolute_import


class DataverseError(Exception):
"""Base exception class for Dataverse-related error."""
pass
Expand Down
11 changes: 6 additions & 5 deletions dataverse/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ def __init__(self, dataset, name, file_id=None):
self.name = sanitize(name)
self.id = file_id

self.download_url = 'http://{0}/api/access/datafile/{1}'.format(
dataset.connection.host, self.id
self.download_url = '{0}/access/datafile/{1}'.format(
dataset.connection.native_base_url, self.id
)
self.edit_media_uri = 'https://{0}/dvn/api/data-deposit/v1.1/swordv2/edit-media/file/{1}'.format(
dataset.connection.host, self.id
edit_media_base = '{0}/edit-media/file/{1}'
self.edit_media_uri = edit_media_base.format(
dataset.connection.sword_base_url, self.id
)

@classmethod
def from_json(cls, dataset, json):
name = json['datafile']['name']
file_id = json['datafile']['id']
return cls(dataset, name, file_id)
return cls(dataset, name, file_id)
1 change: 0 additions & 1 deletion dataverse/settings/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import os

TEST_HOST = 'apitest.dataverse.org'
TEST_TOKEN = 'changeme'

HERE = os.path.dirname(os.path.abspath(__file__))
BASE_PATH = os.path.abspath(os.path.join(HERE, os.pardir))
Expand Down
71 changes: 58 additions & 13 deletions dataverse/test/test_dataverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

import uuid
import httpretty
import requests

from dataverse.connection import Connection
from dataverse.dataset import Dataset
from dataverse.settings import TEST_HOST, TEST_TOKEN
from dataverse.settings import TEST_HOST
from dataverse.test.config import PICS_OF_CATS_DATASET, ATOM_DATASET, EXAMPLE_FILES
from dataverse import exceptions
from dataverse import utils
Expand All @@ -16,6 +17,44 @@
logging.basicConfig(level=logging.ERROR)


class DataverseServerTestBase(object):
"""Create a temporary user on `TEST_SERVER` for testing purposes.
This attaches `username`, `password`, and `token` to the class.
"""

@classmethod
def setup_class(cls):
"""Create a temporary user"""
cls.username = str(uuid.uuid1())
cls.password = 'p4ssw0rd'
key = 'burrito' # hardcoded on test servers
user_url = 'https://{0}/api/builtin-users?key={1}&password={2}'.format(
TEST_HOST, key, cls.password,
)
user_json = {
'email': '{0}@gmail.com'.format(cls.username),
'firstName': 'Namey',
'lastName': 'Namington',
'userName': cls.username,
}

resp = requests.post(user_url, json=user_json)
cls.token = resp.json()['data']['apiToken']

@classmethod
def teardown_class(cls):
"""Delete the temporary user.
Note that this will fail if the user has any non-deleted content.
"""
delete_url = 'https://{0}/api/admin/authenticatedUsers/{1}/'.format(
TEST_HOST, cls.username,
)
resp = requests.delete(delete_url)
assert resp.status_code == 200


class TestUtils(object):

def test_get_element(self):
Expand Down Expand Up @@ -64,13 +103,13 @@ def test_format_term_replace(self):
assert formatted_term == '{http://purl.org/dc/terms/}identifier'


class TestConnection(object):
class TestConnection(DataverseServerTestBase):

def test_connect(self):
connection = Connection(TEST_HOST, TEST_TOKEN)
connection = Connection(TEST_HOST, self.token)

assert connection.host == TEST_HOST
assert connection.token == TEST_TOKEN
assert connection.token == self.token
assert connection._service_document

def test_connect_unauthorized(self):
Expand All @@ -81,15 +120,17 @@ def test_connect_unauthorized(self):
def test_connect_unknown_failure(self):
httpretty.register_uri(
httpretty.GET,
'https://{host}/dvn/api/data-deposit/v1.1/swordv2/service-document'.format(host=TEST_HOST),
'https://{host}/dvn/api/data-deposit/v1.1/swordv2/service-document'.format(
host=TEST_HOST
),
status=400,
)

with pytest.raises(exceptions.ConnectionError):
Connection(TEST_HOST, TEST_TOKEN)
Connection(TEST_HOST, self.token)

def test_create_dataverse(self):
connection = Connection(TEST_HOST, TEST_TOKEN)
connection = Connection(TEST_HOST, self.token)
alias = str(uuid.uuid1()) # must be unique
connection.create_dataverse(
alias,
Expand All @@ -105,7 +146,7 @@ def test_create_dataverse(self):
connection.delete_dataverse(dataverse)

def test_delete_dataverse(self):
connection = Connection(TEST_HOST, TEST_TOKEN)
connection = Connection(TEST_HOST, self.token)
alias = str(uuid.uuid1()) # must be unique
dataverse = connection.create_dataverse(
alias,
Expand All @@ -119,7 +160,7 @@ def test_delete_dataverse(self):
assert dataverse is None

def test_get_dataverses(self):
connection = Connection(TEST_HOST, TEST_TOKEN)
connection = Connection(TEST_HOST, self.token)
original_dataverses = connection.get_dataverses()
assert isinstance(original_dataverses, list)

Expand All @@ -142,7 +183,7 @@ def test_get_dataverses(self):
assert [dv.alias for dv in current_dataverses] == [dv.alias for dv in original_dataverses]

def test_get_dataverse(self):
connection = Connection(TEST_HOST, TEST_TOKEN)
connection = Connection(TEST_HOST, self.token)
alias = str(uuid.uuid1()) # must be unique
assert connection.get_dataverse(alias) is None

Expand Down Expand Up @@ -190,15 +231,18 @@ def test_init_from_xml(self):
tag='rights'
).text
assert title == 'Roasting at Home'
assert publisher == 'Creative Commons CC-BY 3.0 (unported) http://creativecommons.org/licenses/by/3.0/'
assert publisher == 'Creative Commons CC-BY 3.0 (unported) ' \
'http://creativecommons.org/licenses/by/3.0/'


class TestDatasetOperations(object):
class TestDatasetOperations(DataverseServerTestBase):

@classmethod
def setup_class(cls):
super(TestDatasetOperations, cls).setup_class()

print('Connecting to Dataverse host at {0}'.format(TEST_HOST))
cls.connection = Connection(TEST_HOST, TEST_TOKEN)
cls.connection = Connection(TEST_HOST, cls.token)

print('Creating test Dataverse')
cls.alias = str(uuid.uuid1())
Expand All @@ -212,6 +256,7 @@ def setup_class(cls):

@classmethod
def teardown_class(cls):
super(TestDatasetOperations, cls).setup_class()

print('Removing test Dataverse')
cls.connection.delete_dataverse(cls.dataverse)
Expand Down
7 changes: 5 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ information:

```python
TEST_HOST = 'apitest.dataverse.org' # or 'dataverse-demo.iq.harvard.edu'
TEST_TOKEN = '' # Token can be generated at {host}/account/apitoken
```

Do not commit this file.
Expand All @@ -51,4 +50,8 @@ To run tests:

Or, to run a specific test:

$ py.test dataverse/test/test_dataverse.py::TestClassName::test_method_name
$ py.test dataverse/test/test_dataverse.py::TestClassName::test_method_name

To check for style:

$ flake8 .
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 100
exclude = dataverse/__init__.py,dataverse/settings/__init__.py
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
'lxml>=3.2.5',
]

TEST_REQUIRES = [
TESTS_REQUIRE = [
'httpretty>=0.8.8',
'pytest>=2.7.0',
'flake8>=2.4.0',
]


Expand Down Expand Up @@ -42,6 +43,6 @@ def read(fname):
'Natural Language :: English',
],
test_suite='dataverse/test',
tests_require=TEST_REQUIRES,
tests_require=TESTS_REQUIRE,
cmdclass={'test': unittest}
)

0 comments on commit f84b980

Please sign in to comment.