[406] | 1 | package gscf |
---|
| 2 | |
---|
[653] | 3 | import dbnp.studycapturing.Study |
---|
| 4 | import dbnp.studycapturing.Template |
---|
| 5 | import grails.test.GrailsUnitTestCase |
---|
| 6 | import dbnp.studycapturing.SamplingEvent |
---|
| 7 | import dbnp.studycapturing.Sample |
---|
[662] | 8 | import dbnp.studycapturing.TemplateFieldType |
---|
[774] | 9 | import dbnp.studycapturing.Subject |
---|
[812] | 10 | import dbnp.studycapturing.EventGroup |
---|
[406] | 11 | |
---|
| 12 | /** |
---|
[653] | 13 | * Test the creation of a Sample and its TemplateEntity functionality on data model level |
---|
[406] | 14 | * |
---|
| 15 | * @author keesvb |
---|
| 16 | * @since 20100511 |
---|
| 17 | * @package dbnp.studycapturing |
---|
| 18 | * |
---|
| 19 | * Revision information: |
---|
| 20 | * $Rev: 817 $ |
---|
| 21 | * $Author: keesvb $ |
---|
| 22 | * $Date: 2010-08-17 12:42:54 +0000 (di, 17 aug 2010) $ |
---|
| 23 | */ |
---|
| 24 | |
---|
[653] | 25 | class SampleTests extends StudyTests { |
---|
[406] | 26 | |
---|
[653] | 27 | // This test extends StudyTests, so that we have a test study to assign as a parent study |
---|
| 28 | |
---|
[737] | 29 | final String testSampleName = "Test sample @XYZ!" |
---|
[653] | 30 | final String testSampleTemplateName = "Human blood sample" |
---|
| 31 | |
---|
| 32 | final String testSamplingEventName = "Test sampling event" |
---|
| 33 | final String testSamplingEventTemplateName = "Blood extraction" |
---|
| 34 | final long testSamplingEventTime = 34534534L |
---|
[812] | 35 | final long testSamplingEventDuration = 1000L |
---|
| 36 | final String testEventGroupName = "Test Group" |
---|
[653] | 37 | |
---|
| 38 | |
---|
[406] | 39 | protected void setUp() { |
---|
| 40 | super.setUp() |
---|
| 41 | |
---|
[653] | 42 | // Retrieve the study that should have been created in StudyTests |
---|
| 43 | def study = Study.findByTitle(testStudyName) |
---|
| 44 | assert study |
---|
[406] | 45 | |
---|
[653] | 46 | // Look up sampling event template |
---|
| 47 | def samplingEventTemplate = Template.findByName(testSamplingEventTemplateName) |
---|
| 48 | assert samplingEventTemplate |
---|
| 49 | |
---|
[812] | 50 | // Look up sample template |
---|
| 51 | def sampleTemplate = Template.findByName(testSampleTemplateName) |
---|
| 52 | assert sampleTemplate |
---|
| 53 | |
---|
[653] | 54 | // Create parent sampling event |
---|
| 55 | def samplingEvent = new SamplingEvent( |
---|
| 56 | startTime: testSamplingEventTime, |
---|
[812] | 57 | duration: testSamplingEventDuration, |
---|
| 58 | template: samplingEventTemplate, |
---|
| 59 | sampleTemplate: sampleTemplate |
---|
[406] | 60 | ) |
---|
| 61 | |
---|
[774] | 62 | // The SamplingEvent should not validate at this point because it doesn't have a parent study |
---|
| 63 | assert !samplingEvent.validate() |
---|
| 64 | |
---|
| 65 | study.addToSamplingEvents(samplingEvent) |
---|
| 66 | // It should do fine now |
---|
[653] | 67 | assert samplingEvent.validate() |
---|
[654] | 68 | assert samplingEvent.save(flush:true) |
---|
[406] | 69 | |
---|
[653] | 70 | // Create sample with the retrieved study as parent |
---|
| 71 | def sample = new Sample( |
---|
| 72 | name: testSampleName, |
---|
| 73 | template: sampleTemplate, |
---|
| 74 | parentEvent: samplingEvent |
---|
| 75 | ) |
---|
| 76 | |
---|
| 77 | // At this point, the sample should not validate, because it doesn't have a parent study assigned |
---|
| 78 | assert !sample.validate() |
---|
| 79 | |
---|
| 80 | // Add the sample to the retrieved parent study |
---|
| 81 | study.addToSamples(sample) |
---|
| 82 | assert study.samples.find { it.name == sample.name} |
---|
| 83 | |
---|
| 84 | // Now, the sample should validate |
---|
| 85 | if (!sample.validate()) { |
---|
| 86 | sample.errors.each { println it} |
---|
| 87 | } |
---|
| 88 | assert sample.validate() |
---|
| 89 | |
---|
| 90 | // Make sure the sample is saved to the database |
---|
| 91 | assert sample.save(flush: true) |
---|
| 92 | |
---|
[406] | 93 | } |
---|
| 94 | |
---|
| 95 | void testSave() { |
---|
[812] | 96 | |
---|
[653] | 97 | // Try to retrieve the sample and make sure it's the same |
---|
| 98 | def sampleDB = Sample.findByName(testSampleName) |
---|
| 99 | assert sampleDB |
---|
| 100 | assert sampleDB.name.equals(testSampleName) |
---|
| 101 | assert sampleDB.template.name.equals(testSampleTemplateName) |
---|
| 102 | assert sampleDB.parentEvent |
---|
| 103 | assert sampleDB.parentEvent.startTime.equals(testSamplingEventTime) |
---|
[412] | 104 | |
---|
[812] | 105 | println "The sample has parentEvent ${sampleDB.parentEvent.encodeAsHTML()}" |
---|
[653] | 106 | // A sample without a name should not be saveable |
---|
| 107 | sampleDB.name = null |
---|
| 108 | assert !sampleDB.validate() |
---|
| 109 | |
---|
| 110 | // A sample without a parent SamplingEvent should not be saveable |
---|
| 111 | sampleDB.name = testSampleName |
---|
| 112 | sampleDB.parentEvent = null |
---|
| 113 | assert !sampleDB.validate() |
---|
[406] | 114 | } |
---|
| 115 | |
---|
[737] | 116 | void testDelete() { |
---|
| 117 | def sampleDB = Sample.findByName(testSampleName) |
---|
| 118 | sampleDB.delete() |
---|
| 119 | try { |
---|
| 120 | sampleDB.save() |
---|
| 121 | assert false // The save should not succeed since the sample is referenced by a study |
---|
| 122 | } |
---|
| 123 | catch(org.springframework.dao.InvalidDataAccessApiUsageException e) { |
---|
| 124 | sampleDB.discard() |
---|
| 125 | assert true // OK, correct exception (at least for the in-mem db, for PostgreSQL it's probably a different one...) |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | // Now, delete the sample from the study samples collection, and then the delete action should be cascaded to the sample itself |
---|
| 129 | def study = Study.findByTitle(testStudyName) |
---|
| 130 | assert study |
---|
| 131 | study.removeFromSamples sampleDB |
---|
| 132 | |
---|
| 133 | // Make sure the sample doesn't exist anymore at this point |
---|
| 134 | assert !Sample.findByName(testSampleName) |
---|
[774] | 135 | assert Sample.count() == 0 |
---|
[737] | 136 | assert study.samples.size() == 0 |
---|
| 137 | } |
---|
| 138 | |
---|
[774] | 139 | void testDeleteViaParentSubject() { |
---|
| 140 | |
---|
| 141 | def sampleDB = Sample.findByName(testSampleName) |
---|
| 142 | assert sampleDB |
---|
| 143 | |
---|
| 144 | // Retrieve the parent study |
---|
| 145 | def study = Study.findByTitle(testStudyName) |
---|
| 146 | assert study |
---|
| 147 | |
---|
| 148 | def subject = SubjectTests.createSubject(study) |
---|
| 149 | assert subject |
---|
| 150 | |
---|
| 151 | sampleDB.parentSubject = subject |
---|
| 152 | assert sampleDB.validate() |
---|
| 153 | assert sampleDB.save() |
---|
| 154 | |
---|
| 155 | // Use the deleteSubject method |
---|
| 156 | def msg = study.deleteSubject(subject) |
---|
| 157 | println msg |
---|
| 158 | assert study.save() |
---|
| 159 | |
---|
| 160 | assert !study.subjects.contains(subject) |
---|
| 161 | |
---|
[812] | 162 | assert !Subject.findByName(subject.name) |
---|
[774] | 163 | assert !Sample.findByName(testSampleName) |
---|
| 164 | |
---|
| 165 | assert Subject.count() == 0 |
---|
| 166 | assert Sample.count() == 0 |
---|
| 167 | |
---|
| 168 | } |
---|
| 169 | |
---|
[812] | 170 | void testDeleteViaParentSamplingEvent() { |
---|
| 171 | |
---|
| 172 | def sampleDB = Sample.findByName(testSampleName) |
---|
| 173 | assert sampleDB |
---|
| 174 | |
---|
| 175 | // Retrieve the parent study |
---|
| 176 | def study = Study.findByTitle(testStudyName) |
---|
| 177 | assert study |
---|
| 178 | |
---|
| 179 | def event = sampleDB.parentEvent |
---|
| 180 | assert event |
---|
| 181 | |
---|
| 182 | // Use the deleteSamplingEvent method |
---|
| 183 | def msg = study.deleteSamplingEvent(event) |
---|
| 184 | println msg |
---|
| 185 | assert study.save() |
---|
| 186 | |
---|
| 187 | assert !study.samplingEvents.contains(event) |
---|
| 188 | |
---|
| 189 | assert !SamplingEvent.findByStartTime(testSamplingEventTime) |
---|
| 190 | assert !Sample.findByName(testSampleName) |
---|
| 191 | |
---|
| 192 | assert SamplingEvent.count() == 0 |
---|
| 193 | assert Sample.count() == 0 |
---|
| 194 | |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | void testDeleteViaParentEventGroup() { |
---|
| 198 | |
---|
| 199 | def sampleDB = Sample.findByName(testSampleName) |
---|
| 200 | assert sampleDB |
---|
| 201 | |
---|
| 202 | // Retrieve the parent study |
---|
| 203 | def study = Study.findByTitle(testStudyName) |
---|
| 204 | assert study |
---|
| 205 | |
---|
| 206 | // Retrieve the sample's sampling event |
---|
| 207 | def event = sampleDB.parentEvent |
---|
| 208 | assert event |
---|
| 209 | |
---|
| 210 | // Create a subject and add it at the sample's parent |
---|
| 211 | def subject = SubjectTests.createSubject(study) |
---|
| 212 | assert subject |
---|
| 213 | sampleDB.parentSubject = subject |
---|
| 214 | assert sampleDB.validate() |
---|
| 215 | assert sampleDB.save() |
---|
| 216 | |
---|
| 217 | // Create an event group in this study with the sample's sampling event |
---|
| 218 | def group = new EventGroup( |
---|
| 219 | name: testEventGroupName |
---|
| 220 | ) |
---|
| 221 | study.addToEventGroups(group) |
---|
[817] | 222 | assert group.validate() |
---|
| 223 | |
---|
| 224 | |
---|
[812] | 225 | group.addToSubjects(subject) |
---|
| 226 | group.addToSamplingEvents(event) |
---|
| 227 | assert study.eventGroups.find { it.name == group.name} |
---|
| 228 | assert group.validate() |
---|
| 229 | assert study.save() |
---|
| 230 | |
---|
| 231 | // Use the deleteSamplingEvent method |
---|
| 232 | def msg = study.deleteEventGroup(group) |
---|
| 233 | println msg |
---|
| 234 | assert study.save() |
---|
| 235 | |
---|
| 236 | assert !study.eventGroups.contains(group) |
---|
| 237 | assert !EventGroup.findByName(testEventGroupName) |
---|
| 238 | assert !Sample.findByName(testSampleName) |
---|
| 239 | |
---|
| 240 | assert EventGroup.count() == 0 |
---|
| 241 | assert Sample.count() == 0 |
---|
| 242 | |
---|
| 243 | } |
---|
| 244 | |
---|
[653] | 245 | void testStudyRelation() { |
---|
| 246 | // Retrieve the parent study |
---|
[412] | 247 | def study = Study.findByTitle(testStudyName) |
---|
| 248 | assert study |
---|
| 249 | |
---|
[654] | 250 | // Test giveSampleTemplates |
---|
| 251 | def templates = study.giveSampleTemplates() |
---|
[653] | 252 | assert templates |
---|
| 253 | assert templates.size() == 1 |
---|
[654] | 254 | assert templates.asList().first().name == testSampleTemplateName |
---|
[412] | 255 | |
---|
[653] | 256 | // Test if the sample is in the samples collection |
---|
| 257 | assert study.samples |
---|
| 258 | assert study.samples.size() == 1 |
---|
| 259 | assert study.samples.first().name == testSampleName |
---|
[412] | 260 | } |
---|
| 261 | |
---|
[654] | 262 | |
---|
| 263 | void testParentStudy() { |
---|
| 264 | def sample = Sample.findByName(testSampleName) |
---|
| 265 | assert sample |
---|
| 266 | |
---|
| 267 | assert sample.parent |
---|
| 268 | assert sample.parent.code == testStudyCode |
---|
| 269 | } |
---|
| 270 | |
---|
| 271 | void testSampleUniqueNameConstraint() { |
---|
| 272 | def sample = Sample.findByName(testSampleName) |
---|
| 273 | assert sample |
---|
| 274 | |
---|
| 275 | def study = sample.parent |
---|
| 276 | assert study |
---|
| 277 | |
---|
| 278 | def sample2 = new Sample( |
---|
| 279 | name: testSampleName, |
---|
[663] | 280 | template: sample.template, |
---|
| 281 | parentEvent: sample.parentEvent |
---|
[654] | 282 | ) |
---|
| 283 | |
---|
| 284 | // Add the sample to the retrieved parent study |
---|
| 285 | study.addToSamples(sample2) |
---|
| 286 | |
---|
| 287 | // At this point, the sample should not validate or save, because there is already a sample with that name in the study |
---|
| 288 | assert !sample2.validate() |
---|
| 289 | assert !sample2.save(flush:true) |
---|
| 290 | |
---|
| 291 | } |
---|
| 292 | |
---|
[653] | 293 | void testFindViaSamplingEvent() { |
---|
| 294 | // Try to retrieve the sampling event by using the time... |
---|
| 295 | // (should be also the parent study but that's not yet implemented) |
---|
| 296 | def samplingEventDB = SamplingEvent.findByStartTime(testSamplingEventTime) |
---|
| 297 | assert samplingEventDB |
---|
[406] | 298 | |
---|
[653] | 299 | def samples = samplingEventDB.getSamples() |
---|
| 300 | assert samples |
---|
| 301 | assert samples.size() == 1 |
---|
| 302 | assert samples.first().name == testSampleName |
---|
| 303 | } |
---|
[406] | 304 | |
---|
[653] | 305 | void testDomainFields() { |
---|
[654] | 306 | def sample = Sample.findByName(testSampleName) |
---|
[653] | 307 | assert sample |
---|
| 308 | |
---|
| 309 | // Make sure the domain fields exist |
---|
| 310 | assert sample.fieldExists('name') |
---|
| 311 | assert sample.fieldExists('material') |
---|
| 312 | |
---|
| 313 | // Make sure they are domain fields |
---|
| 314 | assert sample.isDomainField('name') |
---|
| 315 | assert sample.isDomainField('material') |
---|
| 316 | |
---|
[662] | 317 | // Make sure that they have the right type |
---|
| 318 | assert sample.giveFieldType('name') == TemplateFieldType.STRING |
---|
| 319 | assert sample.giveFieldType('material') == TemplateFieldType.ONTOLOGYTERM |
---|
| 320 | |
---|
[406] | 321 | } |
---|
| 322 | |
---|
| 323 | protected void tearDown() { |
---|
| 324 | super.tearDown() |
---|
| 325 | } |
---|
| 326 | |
---|
[653] | 327 | } |
---|