def populate(self, app, db_session): from datetime import date import transaction from occams_datastore import models as datastore from occams_studies import models as studies # Any view-dependent data goes here with transaction.manager: user = datastore.User(key=USERID) drsc = studies.Study(name=u'drsc', title=u'DRSC', short_title=u'dr', code=u'drs', consent_date=date.today(), is_randomized=False) ucsd = studies.Study(name=u'ucsd', title=u'UCSD', short_title=u'ucsd', code=u'ucsd', consent_date=date.today(), is_randomized=False) db_session.add(user) db_session.add(drsc) db_session.add(ucsd) db_session.flush()
def test_enable(self, req, db_session, check_csrf_token): """ It should successfully add a schema to a cycle """ from datetime import date from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'Test', publish_date=date.today()) cycle = models.Cycle(name='week-1', title=u'Week 1', week=1) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) db_session.add_all([study, schema]) db_session.flush() req.json_body = { 'schema': schema.name, 'cycle': cycle.id, 'enabled': True } self._call_fut(study, req) assert schema in cycle.schemata
def test_enforce_unique_name(self, req, db_session, check_csrf_token): """ It should make sure the name stays unique when adding new studies """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams_studies import models study = models.Study(name='some-study', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) db_session.add_all([study]) db_session.flush() req.json_body = { 'title': u'Some Study', 'short_title': u'sfstudy', 'code': u'111', 'consent_date': str(date.today()) } with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(models.StudyFactory(None), req) assert 'Does not yield a unique URL.' in \ excinfo.value.json['errors']['title']
def test_success(self, req, db_session, check_csrf_token): """ It should remove the schema from the study and cascade to its cycles """ from datetime import date from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) cycle = models.Cycle(name='week-1', title=u'Week 1', week=1, schemata=set([schema])) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) db_session.add_all([study, schema]) db_session.flush() req.matchdict = {'schema': schema.name} self._call_fut(study, req) assert schema not in study.schemata assert schema not in cycle.schemata
def test_fail_if_not_same_schema(self, req, db_session, check_csrf_token): """ It should fail if the schema and versions do not match """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) db_session.add_all([study, schema]) db_session.flush() req.json_body = {'schema': u'otherform', 'versions': [schema.id]} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'Incorrect versions' in \ excinfo.value.json['errors']['versions']
def test_fail_if_termination_schema(self, req, db_session, check_csrf_token): """ It should not allow termination schemata to be used as study schemata """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), termination_schema=schema) db_session.add_all([study, schema]) db_session.flush() req.json_body = {'schema': schema.name, 'versions': [schema.id]} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'already a termination form' in \ excinfo.value.json['errors']['schema'].lower()
def test_update_cycles(self, req, db_session, check_csrf_token): """ It should also update cycle versions """ from datetime import date, timedelta from occams_datastore import models as datastore from occams_studies import models today = date.today() tomorrow = today + timedelta(days=1) v1 = datastore.Schema(name=u'test', title=u'', publish_date=today) v2 = datastore.Schema(name=u'test', title=u'', publish_date=tomorrow) cycle = models.Cycle(name=u'wk-001', title=u'WK-001', schemata=set([v1])) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', cycles=[cycle], schemata=set([v1]), consent_date=date.today()) db_session.add_all([study, v1, v2]) db_session.flush() req.json_body = {'schema': v1.name, 'versions': [v2.id]} self._call_fut(study, req) assert v2 in study.schemata # v2 should have been passed on to the cycle using it as well assert v2 in cycle.schemata
def test_exclude_schema_used_versions(self, req, db_session, check_csrf_token): """ It should exclude general versions already used by the form (editing) """ from datetime import date, timedelta from webob.multidict import MultiDict from occams_datastore import models as datastore from occams_studies import models today = date.today() tomorrow = today + timedelta(days=1) y0 = datastore.Schema(name='y', title=u'Y', publish_date=today) y1 = datastore.Schema(name='y', title=u'Y', publish_date=tomorrow) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([y0])) db_session.add_all([y0, y1, study]) db_session.flush() req.GET = MultiDict() res = self._call_fut(study, req) assert 1 == len(res['schemata']) assert str(tomorrow) == res['schemata'][0]['publish_date']
def test_has_enrollments(self, req, db_session, config, check_csrf_token): """ It should not allow deletion of a study if it has enrollments (unless administrator) """ from datetime import date from pyramid.httpexceptions import HTTPForbidden from occams_studies import models study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) enrollment = models.Enrollment(study=study, consent_date=date.today(), patient=models.Patient(site=models.Site( name='ucsd', title=u'UCSD'), pid=u'12345')) db_session.add_all([study, enrollment]) db_session.flush() # Should not be able to delete if not an admin config.testing_securitypolicy(permissive=False) with pytest.raises(HTTPForbidden): self._call_fut(study, req) config.testing_securitypolicy(permissive=True) self._call_fut(study, req) assert 0 == db_session.query(models.Study).count()
def test_basic(self, req, db_session, check_csrf_token): """ It should allow adding a schema to a study """ from datetime import date from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) db_session.add_all([study, schema]) db_session.flush() req.json_body = {'schema': schema.name, 'versions': [schema.id]} self._call_fut(study, req) assert schema in study.schemata
def test_add_to_patient(self, req, db_session): from datetime import date from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name=u'schema', title=u'Schema', publish_date=date.today()) study = models.Study(name='some-study', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([schema])) site = models.Site(name=u'somewhere', title=u'Somewhere') patient = models.Patient(pid=u'12345', site=site) db_session.add_all([study, patient]) db_session.flush() req.method = 'POST' req.matchdict = {'patient': patient} req.json_body = { 'schema': schema.id, 'collect_date': str(date.today()), } factory = models.FormFactory(req, patient) self._call_fut(factory, req) contexts = db_session.query(datastore.Context).all() assert len(contexts) == 1 assert contexts[0].entity.schema == schema
def test_by_enrollment_number(self, req, db_session): """ It should be able to search by Enrollment Number """ from datetime import date from occams_studies import models from webob.multidict import MultiDict study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) site_la = models.Site(name=u'la', title=u'LA') patient = models.Patient(site=site_la, pid=u'12345', enrollments=[ models.Enrollment( study=study, reference_number=u'xyz', consent_date=date.today()) ]) db_session.add_all([site_la, patient]) db_session.flush() req.GET = MultiDict([('query', u'xyz')]) res = self._call_fut(models.PatientFactory(req), req) assert patient.pid == res['patients'][0]['pid']
def test_edit_unique_name(self, req, db_session): """ It should allow the cycle to be able to change its unique name """ from datetime import date from occams_studies import models cycle = models.Cycle(name='week-1', title=u'Week 1', week=1) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle]) db_session.add_all([study]) db_session.flush() req.json_body = { 'name': 'somestudy', 'title': cycle.title, 'week': cycle.week } res = self._call_fut(cycle, req) assert res is not None
def test_enforce_unique_name(self, req, db_session): """ It should make sure the name stays unique when adding new cycles """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams_studies import models cycle = models.Cycle(name='week-1', title=u'Week 1', week=1) study = models.Study(name=u'some-study', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle]) db_session.add_all([study]) db_session.flush() req.json_body = {'title': u'Week 1', 'week': 2} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study['cycles'], req) assert 'not yield a unique' in \ excinfo.value.json['errors']['title'].lower()
def test_fail_if_not_published(self, req, db_session, check_csrf_token): """ It should fail if the schema is not published """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'') study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) db_session.add_all([study, schema]) db_session.flush() db_session.execute(models.patient_schema_table.insert().values( {'schema_id': schema.id})) req.json_body = {'schema': schema.name, 'versions': [schema.id]} with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'not published' in \ excinfo.value.json['errors']['versions-0']
def test_exclude_schema(self, req, db_session, check_csrf_token): """ It should exlude general forms used by the study (editing) """ from datetime import date from webob.multidict import MultiDict from occams_datastore import models as datastore from occams_studies import models x = datastore.Schema(name='x', title=u'x', publish_date=date.today()) y = datastore.Schema(name='y', title=u'Y', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([x])) db_session.add_all([x, y, study]) db_session.flush() req.GET = MultiDict() res = self._call_fut(study, req) assert 1 == len(res['schemata']) assert 'y' == res['schemata'][0]['name']
def test_edit_unique_name(self, req, db_session, check_csrf_token): """ It should allow the study to be able to change its unique name """ from datetime import date from occams_studies import models study = models.Study(name='some-study', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) db_session.add_all([study]) db_session.flush() req.json_body = { 'title': u'New Study Title', 'short_title': study.short_title, 'code': study.code, 'consent_date': str(study.consent_date) } res = self._call_fut(study, req) assert res is not None
def test_data_with_early_test(self, db_session, study_code): """ It should output earlytest ids (for backwards-compatibilty) """ from datetime import date from occams_studies import models plan = self._create_one(db_session) patient = models.Patient( pid=u'xxx-xxx', site=models.Site(name=u'someplace', title=u'Some Place'), enrollments=[ models.Enrollment(consent_date=date.today(), reference_number=u'76C000000', study=models.Study(name=u'some_study', code=study_code, consent_date=date.today(), short_title=u'smstdy', title=u'Some Study')) ]) db_session.add(patient) query = plan.data() data = query.one()._asdict() assert data['early_id'] == patient.enrollments[0].reference_number
def test_by_ids( self, req, db_session, ): """ It should allow search via direct ids (for pre-entered values) """ from datetime import date from occams_studies import models from webob.multidict import MultiDict study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle1 = models.Cycle(name='week-1', title=u'Foo Week 1', week=1) cycle2 = models.Cycle(name='week-2', title=u'Bar Week 2', week=2) patient = models.Patient(site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') study.cycles.append(cycle1) study.cycles.append(cycle2) db_session.add_all([patient, study]) db_session.flush() req.GET = MultiDict([('ids', cycle1.id)]) res = self._call_fut(patient['visits'], req) assert cycle1.id == res['cycles'][0]['id']
def test_process_import(self, db_session): from datetime import date from occams_datastore import models as datastore from occams_studies import models as studies from occams_imports.views.codebook import process_import attr_dict = {} schema = datastore.Schema(name=u'test_name', title=u'test_title', publish_date=date.today()) study = studies.Study(name=u'test_site', title=u'test_title', short_title=u'tt', code=u'tt1', consent_date=date.today(), is_randomized=False) process_import(schema, attr_dict, study, db_session) imported_study = (db_session.query( studies.Study).filter(studies.Study.title == study.title)).one() assert imported_study.title == study.title
def test_update_patient(self, req, db_session, check_csrf_token): """ It should also mark the patient as modified """ from datetime import date from occams_studies import models study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today()) cycle1 = models.Cycle(study=study, name='week-1', title=u'', week=1) patient = models.Patient(site=models.Site(name=u'ucsd', title=u'UCSD'), pid=u'12345') db_session.add_all([patient, study]) db_session.flush() old_modify_date = patient.modify_date req.json_body = { 'cycles': [str(cycle1.id)], 'visit_date': str(date.today()) } self._call_fut(patient['visits'], req) assert old_modify_date < patient.modify_date
def populate(self, app, db_session): import transaction from occams_studies import models as studies from occams_datastore import models as datastore from datetime import date # Any view-dependent data goes here # Webtests will use a different scope for its transaction with transaction.manager: user = datastore.User(key=USERID) db_session.info['blame'] = user db_session.add(user) db_session.flush() site = studies.Site(name=u'UCSD', title=u'UCSD', description=u'UCSD Campus', create_date=date.today()) patient = studies.Patient(initials=u'ian', nurse=u'*****@*****.**', site=site, pid=u'123') study = studies.Study( name=u'test_study', code=u'test_code', consent_date=date(2014, 12, 23), is_randomized=False, title=u'test_title', short_title=u'test_short', ) db_session.add(study) db_session.add(patient)
def test_get_attributes_value_value(self): """Should return the value to be matched.""" from datetime import date from occams_datastore import models as datastore from occams_studies import models as studies from occams_imports import models study = studies.Study(name=u'UCSD', title=u'UCSD', short_title=u'UCSD', code=u'001', consent_date=date(2015, 01, 01)) schema = datastore.Schema(name=u'PatientRegistrationAndDemographics', title=u'PatientRegistrationAndDemographics', publish_date=date(2013, 02, 25), attributes={ 'birthyear': datastore.Attribute(name=u'birthyear', title=u'birthyear', type=u'number', order=0) }) record = models.SiteData(schema=schema, study=study, data=SITEDATA) source_variable = u'birthyear' choices_mapping = [] target_value = self._call_fut(choices_mapping, record, source_variable, schema) assert target_value == '35'
def populate(self, db_session): from datetime import date from occams_datastore import models as datastore from occams_studies import models as studies drsc = studies.Study(name=u'drsc', title=u'DRSC', short_title=u'dr', code=u'drs', consent_date=date.today(), is_randomized=False) schema1 = datastore.Schema( name=u'demographics', title=u'demographics', publish_date=u'2015-01-01', attributes={ 'question': datastore.Attribute(name=u'question', title=u'question', type=u'choice', order=0, choices={ u'0': datastore.Choice(name=u'0', title=u'always', order=0), u'1': datastore.Choice(name=u'1', title=u'never', order=1) }) }) schema2 = datastore.Schema( name=u'ucsd_demographics', title=u'ucsd_demographics', publish_date=u'2015-01-01', attributes={ 'ucsd_question': datastore.Attribute(name=u'ucsd_question', title=u'ucsd_question', type=u'choice', order=0, choices={ u'0': datastore.Choice(name=u'0', title=u'always', order=0), u'1': datastore.Choice(name=u'1', title=u'never', order=1) }) }) drsc.schemata.add(schema1) drsc.schemata.add(schema2) db_session.add(drsc) db_session.flush()
def populate(self, db_session): from datetime import date from occams_datastore import models as datastore from occams_studies import models as studies drsc = studies.Study(name=u'drsc', title=u'DRSC', short_title=u'dr', code=u'drs', consent_date=date.today(), is_randomized=False) schema1 = datastore.Schema(name=u'demographics', title=u'demographics', publish_date=u'2015-01-01', attributes={ 'myfield': datastore.Attribute(name=u'myfield', title=u'My Field', type=u'string', order=0), 'question': datastore.Attribute(name=u'question', title=u'question', type=u'string', order=0) }) drsc.schemata.add(schema1) db_session.add(drsc) db_session.flush()
def test_success(self, req, db_session, check_csrf_token): """ It should allow removal of entities from a visit. """ from datetime import date, timedelta from pyramid.httpexceptions import HTTPOk from occams_datastore import models as datastore from occams_studies import models cycle = models.Cycle(name='week-1', title=u'', week=1) schema = datastore.Schema(name=u'sample', title=u'', publish_date=date.today()) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), cycles=[cycle], schemata=set([schema])) site = models.Site(name=u'ucsd', title=u'UCSD') default_state = (db_session.query( datastore.State).filter_by(name=u'pending-entry').one()) t_a = date.today() + timedelta(days=5) patient_a = models.Patient(site=site, pid=u'12345') visit_a = models.Visit(patient=patient_a, cycles=[cycle], visit_date=t_a) entity_a_1 = datastore.Entity(schema=schema, collect_date=t_a, state=default_state) entity_a_2 = datastore.Entity(schema=schema, collect_date=t_a, state=default_state) entity_a_3 = datastore.Entity(schema=schema, collect_date=t_a, state=default_state) list(map(visit_a.entities.add, [entity_a_1, entity_a_2, entity_a_3])) db_session.add_all([visit_a, study]) db_session.flush() req.json_body = {'forms': [entity_a_2.id, entity_a_3.id]} res = self._call_fut(visit_a['forms'], req) # refresh the session so we can get a correct listing db_session.expunge_all() visit_a = db_session.query(models.Visit).get(visit_a.id) assert isinstance(res, HTTPOk) assert sorted([e.id for e in [entity_a_1]]) == \ sorted([e.id for e in visit_a.entities])
def test_valid_upload(self, req, db_session, check_csrf_token): """ It should be able to upload a perfectly valid CSV """ import tempfile import csv from datetime import date from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='rand', title=u'Rand', publish_date=date.today(), attributes={ 'criteria': datastore.Attribute(name='criteria', title=u'Criteria', type='string', order=0) }) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', is_randomized=True, randomization_schema=schema, consent_date=date.today()) db_session.add_all([study]) db_session.flush() class DummyUpload: pass with tempfile.NamedTemporaryFile(prefix='nose-', suffix='.exe') as fp: upload = DummyUpload() upload.file = fp upload.filename = fp.name # forget the schema keys writer = csv.writer(fp) writer.writerow( [u'ARM', u'STRATA', u'BLOCKID', u'RANDID', u'CRITERIA']) # noqa writer.writerow( [u'UCSD', u'hints', u'1234567', u'987654', u'is smart']) # noqa fp.flush() req.POST = {'upload': upload} self._call_fut(study, req) stratum = db_session.query(models.Stratum).one() entity = db_session.query(datastore.Entity).one() assert stratum.arm.name == 'UCSD' assert entity in stratum.entities assert entity['criteria'] == 'is smart'
def test_cycle_in_study(self, req, db_session, check_csrf_token): """ It should fail if the cycle is not part of the study """ from datetime import date from pyramid.httpexceptions import HTTPBadRequest from occams_datastore import models as datastore from occams_studies import models schema = datastore.Schema(name='test', title=u'Test', publish_date=date.today()) other_cycle = models.Cycle(name=u'week-1', title=u'Title', week=1) other_study = models.Study(name=u'otherstudy', title=u'Other Study', short_title=u'ostudy', code=u'111', consent_date=date.today(), cycles=[other_cycle]) study = models.Study(name=u'somestudy', title=u'Some Study', short_title=u'sstudy', code=u'000', consent_date=date.today(), schemata=set([schema])) db_session.add_all([study, schema, other_study]) db_session.flush() req.json_body = { 'schema': schema.name, 'cycle': other_cycle.id, 'enabled': True } with pytest.raises(HTTPBadRequest) as excinfo: self._call_fut(study, req) assert 'not a valid choice' in \ excinfo.value.json['errors']['cycle'].lower()
def populate(self, app, db_session): import transaction from occams_studies import models as studies from occams_datastore import models as datastore from datetime import date # Any view-dependent data goes here # Webtests will use a different scope for its transaction with transaction.manager: user = datastore.User(key=USERID) db_session.info['blame'] = user db_session.add(user) db_session.flush() site = studies.Site(name=u'UCSD', title=u'UCSD', description=u'UCSD Campus', create_date=date.today()) patient = studies.Patient(initials=u'ian', nurse=u'*****@*****.**', site=site, pid=u'123') form = datastore.Schema(name=u'test_schema', title=u'test_title', publish_date=date(2015, 1, 1)) study = studies.Study(name=u'test_study', code=u'test_code', consent_date=date(2014, 12, 23), is_randomized=False, title=u'test_title', short_title=u'test_short', schemata=set([form])) cycle = studies.Cycle(name=u'TestCycle', title=u'TestCycle', week=39, study=study) visit = studies.Visit(patient=patient, cycles=[cycle], visit_date='2015-01-01') entity = datastore.Entity(schema=form, collect_date=date(2015, 1, 1)) db_session.add(study) db_session.add(patient) db_session.add(visit) db_session.add(entity) patient.entities.add(entity)
def test_enrollment(self, db_session): """ It should add enrollment-specific metadata to the report """ from datetime import date, timedelta from occams_datastore import models as datastore from occams_studies import models from occams_studies.exports.schema import SchemaPlan schema = datastore.Schema(name=u'termination', title=u'Termination', publish_date=date.today(), attributes={ 'foo': datastore.Attribute( name='foo', title=u'', type='string', order=0, ) }) entity = datastore.Entity(schema=schema, collect_date=date.today()) patient = models.Patient(site=models.Site(name='ucsd', title=u'UCSD'), pid=u'12345', entities=[entity]) study = models.Study(name=u'cooties', short_title=u'CTY', code=u'999', consent_date=date.today() - timedelta(365), title=u'Cooties') enrollment = models.Enrollment( patient=patient, study=study, consent_date=date.today() - timedelta(5), latest_consent_date=date.today() - timedelta(3), termination_date=date.today(), entities=[entity]) db_session.add_all([schema, entity, patient, study, enrollment]) plan = SchemaPlan.from_schema(db_session, schema.name) codebook = list(plan.codebook()) query = plan.data() codebook_columns = [c['field'] for c in codebook] data_columns = [c['name'] for c in query.column_descriptions] record = query.one() assert sorted(codebook_columns) == sorted(data_columns) assert record.site == patient.site.name assert record.pid == patient.pid assert record.enrollment == enrollment.study.name assert record.enrollment_ids == str(enrollment.id) assert record.visit_cycles is None assert record.collect_date == entity.collect_date