Skip to content

Commit 88b65ec

Browse files
author
labkey-ians
committed
Spec 24062: Support Python 3
- Refined the unittests
1 parent 9c1265c commit 88b65ec

11 files changed

+407
-633
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ LabKey Server v11.1 and later.
4444

4545
# Contributing
4646
This library and the LabKey Server are maintained by the LabKey Software Foundation. If you have any questions or need support, please use the [LabKey Server support forum](https://www.labkey.org/wiki/home/page.view?name=support).
47+

test/mock_server_responses.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"""
22
Example server responses to be used for mocking
33
"""
4-
import string
4+
from __future__ import unicode_literals
55
import requests
66

7+
78
try:
89
import mock
910
except ImportError:
@@ -70,12 +71,6 @@ class MockSelectRows(MockLabKey):
7071
api = 'getQuery.api'
7172
default_success_body = '{"columnModel": [{"align": "right", "dataIndex": "Participant ID", "editable": true , "header": "Participant ID", "hidden": false , "required": false , "scale": 10 , "sortable": true , "width": 60 }] , "formatVersion": 8.3 , "metaData": {"description": null , "fields": [{"autoIncrement": false , "calculated": false , "caption": "Participant ID", "conceptURI": null , "defaultScale": "LINEAR", "defaultValue": null , "dimension": false , "excludeFromShifting": false , "ext": {} , "facetingBehaviorType": "AUTOMATIC", "fieldKey": "Participant ID", "fieldKeyArray": ["Participant ID"] , "fieldKeyPath": "Participant ID", "friendlyType": "Integer", "hidden": false , "inputType": "text", "isAutoIncrement": false , "isHidden": false , "isKeyField": false , "isMvEnabled": false , "isNullable": true , "isReadOnly": false , "isSelectable": true , "isUserEditable": true , "isVersionField": false , "jsonType": "int", "keyField": false , "measure": false , "mvEnabled": false , "name": "Participant ID", "nullable": true , "protected": false , "rangeURI": "http://www.w3.org/2001/XMLSchema#int", "readOnly": false , "recommendedVariable": false , "required": false , "selectable": true , "shortCaption": "Participant ID", "shownInDetailsView": true , "shownInInsertView": true , "shownInUpdateView": true , "sqlType": "int", "type": "int", "userEditable": true , "versionField": false }] , "id": "Key", "importMessage": null , "importTemplates": [{"label": "Download Template", "url": ""}] , "root": "rows", "title": "Demographics", "totalProperty": "rowCount"} , "queryName": "Demographics", "rowCount": 224 , "rows": [{ "Participant ID": 133428 } , { "Participant ID": 138488 } , { "Participant ID": 140163 } , { "Participant ID": 144740 } , { "Participant ID": 150489 } ] , "schemaName": "lists"}'
7273

73-
def __init__(self, schema_name, query_name, **kwargs):
74-
MockLabKey.__init__(self, **kwargs)
75-
self.schema_name = schema_name
76-
self.query_name = query_name
77-
78-
7974

8075
class MockInsertRows(MockLabKey):
8176
api = 'insertRows.api'
@@ -98,7 +93,10 @@ class MockLoadBatch(MockLabKey):
9893
default_action = 'assay'
9994
default_success_body = {"assayId": 2809, "batch": {"lsid": "urn:lsid:labkey.com:Experiment.Folder-1721:465ad7db-58d8-1033-a587-7eb0c02c2efe", "createdBy": "", "created": "2015/10/19 18:21:57", "name": "python batch", "modified": "2015/10/19 18:21:57", "modifiedBy": "", "comment": None, "id": 120, "runs": [{"dataOutputs": [], "dataRows": [{"Treatment Group": None, "Start Date": None, "Height _inches_": None, "Comments": None, "Status of Infection": None, "Country": None, "Gender": None, "Group Assignment": None, "Participant ID": None, "Date": None}, {"Treatment Group": None, "Start Date": None, "Height _inches_": None, "Comments": None, "Status of Infection": None, "Country": None, "Gender": None, "Group Assignment": None, "Participant ID": None, "Date": None}, {"Treatment Group": None, "Start Date": None, "Height _inches_": None, "Comments": None, "Status of Infection": None, "Country": None, "Gender": None, "Group Assignment": None, "Participant ID": None, "Date": None}], "dataInputs": [], "created": "2015/10/19 18:21:57", "materialInputs": [{"lsid": "urn:lsid:labkey.com:AssayRunMaterial.Folder-1721:Unknown", "role": "Sample", "created": "2015/10/19 18:21:57", "name": "Unknown", "modified": "2015/10/19 18:21:57", "id": 7641}], "lsid": "urn:lsid:labkey.com:GeneralAssayRun.Folder-1721:465ad7dd-58d8-1033-a587-7eb0c02c2efe", "materialOutputs": [], "createdBy": "", "name": "python upload", "modified": "2015/10/19 18:21:57", "modifiedBy": "", "comment": None, "id": 1526, "properties": {}}], "properties": {"ParticipantVisitResolver": None, "TargetStudy": None}}}
10095

96+
10197
class MockSaveBatch(MockLabKey):
10298
api = 'saveAssayBatch.api'
10399
default_action = 'assay'
104100
default_success_body = {"batches": [{"lsid": "urn:lsid:labkey.com:Experiment.Folder-1721:50666e45-609f-1033-ba4a-ca4935e31f28", "createdBy": "", "created": "2015/10/29 12:17:50", "name": "python batch 7", "modified": "2015/10/29 12:17:51", "modifiedBy": "", "comment": None, "id": 139, "runs": [{"dataOutputs": [], "dataRows": [{"Treatment Group": None, "Start Date": None, "Height _inches_": None, "Comments": None, "Status of Infection": None, "Country": None, "Gender": None, "Group Assignment": None, "Participant ID": None, "Date": None}, {"Treatment Group": None, "Start Date": None, "Height _inches_": None, "Comments": None, "Status of Infection": None, "Country": None, "Gender": None, "Group Assignment": None, "Participant ID": None, "Date": None}, {"Treatment Group": None, "Start Date": None, "Height _inches_": None, "Comments": None, "Status of Infection": None, "Country": None, "Gender": None, "Group Assignment": None, "Participant ID": None, "Date": None}], "dataInputs": [], "created": "2015/10/29 12:17:50", "materialInputs": [{"lsid": "urn:lsid:labkey.com:AssayRunMaterial.Folder-1721:Unknown", "role": "Sample", "created": "2015/10/19 18:21:57", "name": "Unknown", "modified": "2015/10/19 18:21:57", "id": 7641}], "lsid": "urn:lsid:labkey.com:GeneralAssayRun.Folder-1721:50666e47-609f-1033-ba4a-ca4935e31f28", "materialOutputs": [], "createdBy": "", "name": "python upload", "modified": "2015/10/29 12:17:51", "modifiedBy": "", "comment": None, "id": 1673, "properties": {}}], "properties": {"ParticipantVisitResolver": None, "TargetStudy": None}}], "assayId": 2809}
101+
102+

test/test_delete_rows.py

Lines changed: 0 additions & 85 deletions
This file was deleted.

test/test_execute_sql.py

Lines changed: 0 additions & 85 deletions
This file was deleted.

test/test_experiment_api.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
from __future__ import unicode_literals
2+
import unittest
3+
4+
try:
5+
import mock
6+
except ImportError:
7+
import unittest.mock as mock
8+
9+
from labkey.utils import create_server_context
10+
from labkey.experiment import load_batch, save_batch, Batch, Run
11+
from labkey.exceptions import RequestError, QueryNotFoundError, ServerNotFoundError, RequestAuthorizationError
12+
from mock_server_responses import MockLoadBatch, MockSaveBatch
13+
14+
15+
def success_test(test, expected_response, api_method, *args, **expected_kwargs):
16+
with mock.patch('labkey.utils.requests.Session.post') as mock_post:
17+
mock_post.return_value = expected_response
18+
resp = api_method(*args)
19+
20+
# validate call is made as expected
21+
expected_args = expected_kwargs.pop('expected_args')
22+
mock_post.assert_called_once_with(*expected_args, **expected_kwargs)
23+
24+
25+
def throws_error_test(test, expected_error, expected_response, api_method, *args, **expected_kwargs):
26+
with mock.patch('labkey.utils.requests.Session.post') as mock_post:
27+
with test.assertRaises(expected_error):
28+
mock_post.return_value = expected_response
29+
api_method(*args)
30+
31+
# validate call is made as expected
32+
expected_args = expected_kwargs.pop('expected_args')
33+
mock_post.assert_called_once_with(*expected_args, **expected_kwargs)
34+
35+
36+
configs = {
37+
'protocol': 'https://'
38+
, 'server': 'my_testServer:8080'
39+
, 'context_path': 'testPath'
40+
, 'project_path': 'testProject/subfolder'
41+
}
42+
43+
assay_id = 12345
44+
batch_id = 54321
45+
server_context = create_server_context(configs['server'], configs['project_path'], configs['context_path'])
46+
47+
48+
class TestLoadBatch(unittest.TestCase):
49+
50+
def setUp(self):
51+
self.configs = configs.copy()
52+
self.service = MockLoadBatch(**self.configs)
53+
self.expected_kwargs = {
54+
'expected_args': [self.service.get_server_url()]
55+
, 'data': '{"assayId": 12345, "batchId": 54321}'
56+
, 'headers': {'Content-type': 'application/json', 'Accept': 'text/plain'}
57+
}
58+
59+
self.args = [
60+
server_context, assay_id, batch_id
61+
]
62+
63+
def test_success(self):
64+
test = self
65+
success_test(test, self.service.get_successful_response(), load_batch, *self.args, **self.expected_kwargs)
66+
67+
def test_unauthorized(self):
68+
test = self
69+
throws_error_test(test, RequestAuthorizationError, self.service.get_unauthorized_response()
70+
, load_batch, *self.args, **self.expected_kwargs)
71+
72+
def test_query_not_found(self):
73+
test = self
74+
throws_error_test(test, QueryNotFoundError, self.service.get_query_not_found_response()
75+
, load_batch, *self.args, **self.expected_kwargs)
76+
77+
def test_server_not_found(self):
78+
test = self
79+
throws_error_test(test, ServerNotFoundError, self.service.get_server_not_found_response()
80+
, load_batch, *self.args, **self.expected_kwargs)
81+
82+
def test_general_error(self):
83+
test = self
84+
throws_error_test(test, RequestError, self.service.get_general_error_response()
85+
, load_batch, *self.args, **self.expected_kwargs)
86+
87+
88+
class TestSaveBatch(unittest.TestCase):
89+
90+
def setUp(self):
91+
92+
dataRows = []
93+
94+
# Generate the Run object(s)
95+
runTest = Run()
96+
runTest.name = 'python upload'
97+
runTest.data_rows = dataRows
98+
runTest.properties['RunFieldName'] = 'Run Field Value'
99+
100+
# Generate the Batch object(s)
101+
batch = Batch()
102+
batch.runs = [runTest]
103+
# batch.name = 'python batch'
104+
batch.properties['PropertyName'] = 'Property Value'
105+
106+
self.configs = configs.copy()
107+
self.service = MockSaveBatch(**self.configs)
108+
self.expected_kwargs = {
109+
'expected_args': [self.service.get_server_url()]
110+
, 'data': '{"assayId": 12345, "batches": [{"batchProtocolId": 0, "comment": null, "created": null, "createdBy": null, "lsid": null, "modified": null, "modifiedBy": null, "name": null, "properties": {"PropertyName": "Property Value"}, "runs": [{"comment": null, "created": null, "createdBy": null, "dataInputs": [], "dataRows": [], "experiments": [], "filePathRoot": null, "lsid": null, "materialInputs": [], "materialOutputs": [], "modified": null, "modifiedBy": null, "name": "python upload", "properties": {"RunFieldName": "Run Field Value"}}]}]}'
111+
, 'headers': {'Content-type': 'application/json', 'Accept': 'text/plain'}
112+
}
113+
114+
self.args = [
115+
server_context, assay_id, batch
116+
]
117+
118+
def test_success(self):
119+
test = self
120+
success_test(test, self.service.get_successful_response(), save_batch, *self.args, **self.expected_kwargs)
121+
122+
def test_unauthorized(self):
123+
test = self
124+
throws_error_test(test, RequestAuthorizationError, self.service.get_unauthorized_response()
125+
, save_batch, *self.args, **self.expected_kwargs)
126+
127+
def test_query_not_found(self):
128+
test = self
129+
throws_error_test(test, QueryNotFoundError, self.service.get_query_not_found_response()
130+
, save_batch, *self.args, **self.expected_kwargs)
131+
132+
def test_server_not_found(self):
133+
test = self
134+
throws_error_test(test, ServerNotFoundError, self.service.get_server_not_found_response()
135+
, save_batch, *self.args, **self.expected_kwargs)
136+
137+
def test_general_error(self):
138+
test = self
139+
throws_error_test(test, RequestError, self.service.get_general_error_response()
140+
, save_batch, *self.args, **self.expected_kwargs)

0 commit comments

Comments
 (0)