source: trunk/test/unit/dbnp/studycapturing/AssayServiceTests.groovy @ 2060

Last change on this file since 2060 was 2060, checked in by s.h.sikkema@…, 6 years ago
  • removed default value for samples argument in AssayService?.collectAssayData to comply with default value for remoteUser. Made adjustments where necessary
  • updated user guide to new one by Janneke
File size: 12.0 KB
Line 
1package dbnp.studycapturing
2
3import grails.test.*
4import org.apache.poi.ss.usermodel.Workbook
5import org.apache.poi.ss.usermodel.WorkbookFactory
6import org.apache.poi.ss.usermodel.Cell
7import org.dbnp.gdt.*
8import org.dbnp.gdt.AssayModule
9import org.dbnp.gdt.TemplateStringField
10
11/**
12 * AssayServiceTests Test
13 *
14 * @author  s.h.sikkema@gmail.com
15 * @since       20101218
16 * @package     dbnp.studycapturing
17 *
18 * Revision information:
19 * $Rev$
20 * $Author$
21 * $Date$
22 */
23class AssayServiceTests extends GrailsUnitTestCase {
24
25    def service = new AssayService()
26
27    protected void setUp() {
28        super.setUp()
29
30
31        mockDomain(Term,          [ new Term(id: 1, name: 'Human')])
32
33        mockDomain(TemplateField, [ new TemplateField(id: 1, name: 'tf1', type: TemplateFieldType.STRING),
34                                    new TemplateField(id: 2, name: 'tf2', type: TemplateFieldType.STRING),
35                                    new TemplateField(id: 3, name: 'tf3', type: TemplateFieldType.STRING)])
36
37        mockDomain(Template,      [ new Template(id: 1, fields: [TemplateField.get(1), TemplateField.get(2)]),
38                                    new Template(id: 2, fields: [TemplateField.get(3)])])
39
40        def mockGdtService = [getTemplateFieldTypeByCasedName: { a -> TemplateStringField }]
41        def mockLog = [ info:{a->println a},error:{a->println "Error: $a"}]
42
43        mockDomain(Subject,       [ new Subject(gdtService: mockGdtService, id: 1, name:'subject1', template: Template.get(1), species: Term.get(1)),
44                                    new Subject(gdtService: mockGdtService, id: 2, name:'subject2', template: Template.get(2), species: Term.get(1))])
45
46        mockDomain(SamplingEvent, [ new SamplingEvent(id:1, startTime: 2, duration: 5, sampleTemplate: new Template()),
47                                    new SamplingEvent(id:2, startTime: 12, duration: 15, sampleTemplate: new Template())])
48
49        mockDomain(Event,         [ new Event(id: 1, startTime: 6, endTime: 7), new Event(id: 2, startTime: 8, endTime: 9)])//, new Event(id: 2, startTime: 8, endTime: 9)])
50
51        mockDomain(EventGroup,    [ new EventGroup(id:1, name: 'EventGroup1', events: [Event.get(1)], samplingEvents: [SamplingEvent.get(1)]),
52                                    new EventGroup(id:2, name: 'EventGroup2', events: [Event.get(2)], samplingEvents: [SamplingEvent.get(2)])])
53
54        mockDomain(Sample,        [ new Sample(id: 1, name:'sample1', parentSubject: Subject.get(1), parentEvent: SamplingEvent.get(1), parentEventGroup: EventGroup.get(1), sampleUUID: 'uuid1'),
55                                    new Sample(id: 2, name:'sample2', parentSubject: Subject.get(2), parentEvent: SamplingEvent.get(2), parentEventGroup: EventGroup.get(2), sampleUUID: 'uuid2'),
56                                    new Sample(id: 3, name:'sample3', parentSubject: Subject.get(2), parentEvent: SamplingEvent.get(2), parentEventGroup: EventGroup.get(2), sampleUUID: 'uuid3')])
57
58        mockDomain(AssayModule,   [ new AssayModule(id: 1, url: 'http://www.example.com') ])
59
60        mockDomain(Assay,         [ new Assay(id: 1, module: AssayModule.get(1), samples: [Sample.get(1),Sample.get(2), Sample.get(3)]),
61                                    new Assay(id: 2, module: AssayModule.get(1), samples: [])])
62
63        Subject.get(1).metaClass.static.log = mockLog
64
65        Subject.get(1).setFieldValue('tf1', 'tfv1')
66        Subject.get(1).setFieldValue('tf2', 'tfv2')
67        Subject.get(2).setFieldValue('tf3', 'tfv3')
68
69        // mock authenticationService
70        service.authenticationService = [
71                isLoggedIn: { true },
72                logInRemotely: { a, b, c -> },
73                logOffRemotely: { a, b -> },
74                getLoggedInUser: { null }
75        ]
76
77        // mock moduleCommunicationService
78        service.moduleCommunicationService = [
79                isModuleReachable: { a -> true },
80                callModuleMethod: { consumer, path, c, d ->
81                    [['uuid1', 'uuid2', 'uuid3'],
82                     ['measurement1','measurement2','measurement3','measurement4'],
83                     [1,2,3,4,5,6,7,8,9,10,11,12] ]
84                }
85        ]
86
87    }
88
89    protected void tearDown() {
90        super.tearDown()
91    }
92
93    void testExportColumnWiseDataAsExcelFile() {
94
95        def columnData = [
96                Category1: [Column1: [1,2,3], Column2: [4,5,6]],
97                Category2: [Column3: [7,8,9], Column4: [10,11,12], Column5: [13,14,15]],
98                EmptyCategory: [:]
99        ]
100
101        def rowData = [
102                ['Category1','','Category2','',''],
103                ['Column1','Column2','Column3','Column4','Column5'],
104                [1,4,7,10,13],
105                [2,5,8,11,14],
106                [3,6,9,12,15]]
107
108        ByteArrayOutputStream   baos    = new ByteArrayOutputStream(1024)
109        DataOutputStream        dos     = new DataOutputStream(baos)
110
111        service.exportColumnWiseDataToExcelFile(columnData, dos, true)
112
113        ByteArrayInputStream    bais    = new ByteArrayInputStream(baos.toByteArray())
114
115        assertEquals 'Expected Excel contents', rowData, readExcelIntoArray(bais)
116
117    }
118
119    def readExcelIntoArray = { inputStream ->
120
121        Workbook wb = WorkbookFactory.create(inputStream)
122
123        def sheet = wb.getSheetAt(0)
124
125        def readData = []
126
127        sheet.eachWithIndex { row, ri ->
128
129            readData[ri] = []
130
131            row.eachWithIndex { cell, ci ->
132                // TODO: what happens when there are empty cells
133                readData[ri][ci] = (cell.cellType == Cell.CELL_TYPE_NUMERIC) ? cell.numericCellValue : cell.stringCellValue
134
135            }
136
137        }
138
139        readData
140
141    }
142
143    // class to test writing non number/string values to excel
144    class SomeCustomType { String toString() {'13'} }
145
146    void testExportRowWiseDataToExcelFile() {
147
148        SomeCustomType someCustomType = new SomeCustomType()
149
150        def rowData = [
151                ['Category1','','Category2','',''],
152                ['Column1','Column2','Column3','Column4','Column5'],
153                [1,4,7,10,someCustomType],
154                [2,5,8,11,null],
155                [3,6,9,12,15]]
156
157        ByteArrayOutputStream   baos    = new ByteArrayOutputStream(1024)
158        DataOutputStream        dos     = new DataOutputStream(baos)
159
160        service.exportRowWiseDataToExcelFile(rowData, dos, false)
161
162        ByteArrayInputStream    bais    = new ByteArrayInputStream(baos.toByteArray())
163
164        // replace custom type with expected written value
165        rowData[2][4] = '13'
166        rowData[3][4] = ''
167
168        def result = readExcelIntoArray(bais)
169
170        assertEquals 'Excel contents', rowData, result
171
172    }
173   
174    void testExportRowWiseDataToExcelFileWithRealisticData() {
175
176        def rowData = [
177                ['Subject Data', '', '', 'Sampling Event Data', '', '', 'Sample Data', '', ''],
178                ['name', 'species', 'Gender', 'startTime', 'sampleTemplate', 'Sample volume', 'name', 'material', 'Text on vial'],
179                [11, 'Homo Sapiens', 'Male', 367200, 'Human blood sample', 4.5, '11_A', 'blood plasma', 'T8.93650593495392']]
180
181        ByteArrayOutputStream   baos    = new ByteArrayOutputStream(1024)
182        DataOutputStream        dos     = new DataOutputStream(baos)
183
184        service.exportRowWiseDataToExcelFile(rowData, dos, false)
185
186        ByteArrayInputStream    bais    = new ByteArrayInputStream(baos.toByteArray())
187
188        def result = readExcelIntoArray(bais)
189
190        assertEquals 'Excel contents', rowData, result
191    }
192
193    void testTemplateFieldsAreCollected() {
194
195        def assay = Assay.get(1)
196
197        def fieldMap = [
198                'Subject Data':[[name:'tf1', displayName: 'tf1'],[name:'tf2', displayName: 'tf2'],[name:'tf3', displayName: 'tf3'],[name:'species', displayName: 'species'],[name:'name', displayName: 'name']],
199                'Sampling Event Data':[[name:'startTime', displayName: 'startTime'],[name:'duration', displayName: 'duration']],
200                'Sample Data':[[name:'name', displayName: 'name']],
201                'Event Group':[[name:'name', displayName: 'name']]
202        ]
203
204        def measurementTokens = ['measurement1', 'measurement2', 'measurement3', 'measurement4']
205
206        String.metaClass.'encodeAsURL' = {delegate}
207
208        def assayData = service.collectAssayData(assay, fieldMap, measurementTokens, [])
209
210        def sample1index = assayData.'Sample Data'.'name'.findIndexOf{it == 'sample1'}
211        def sample2index = assayData.'Sample Data'.'name'.findIndexOf{it == 'sample2'}
212
213        assertEquals 'Subject template field', ['tfv1',''], assayData.'Subject Data'.tf1[sample1index, sample2index]
214        assertEquals 'Subject template field', ['tfv2',''], assayData.'Subject Data'.tf2[sample1index, sample2index]
215        assertEquals 'Subject template field', ['','tfv3'], assayData.'Subject Data'.tf3[sample1index, sample2index]
216        assertEquals 'Subject species template field', ['Human', 'Human', 'Human'], assayData.'Subject Data'.species*.toString()
217        assertEquals 'Subject name template field', ['subject1','subject2'], assayData.'Subject Data'.name[sample1index, sample2index]
218
219        assertEquals 'Sampling event template fields', ['2s','12s'], assayData.'Sampling Event Data'.startTime[sample1index, sample2index]
220        assertEquals 'Sampling event template fields', ['5s','15s'], assayData.'Sampling Event Data'.duration[sample1index, sample2index]
221//        assertEquals 'Sampling event template fields', '[null, null]', assayData.'Sampling Event Data'.sampleTemplate.toString()
222        assertEquals 'Sample template fields', ['sample1', 'sample2'], assayData.'Sample Data'.name[sample1index, sample2index]
223
224        assertEquals 'Event group names', ['EventGroup1', 'EventGroup2'], assayData.'Event Group'.name[sample1index, sample2index]
225
226        assertEquals 'Module Measurement Data', ['measurement1': [1,2,3], 'measurement2': [4,5,6], 'measurement3': [7,8,9], 'measurement4': [10,11,12]], assayData.'Module Measurement Data'
227    }
228
229//    // Test for out of memory exception when exporting large excel workbooks
230//    // - xls format can handle max 256 columns
231//    // - but, xls format can handle more data (1000000 cells, no problem -> 27.2 MB)
232//    // - we'll need a good method to overcome the xlsx heap space problem
233//    void testExportLargeExcelWorkbook() {
234//
235//        def file    = new File( '/tmp', 'tmpFile.xls' )
236//
237//        def os      = file.newOutputStream()
238//
239//        def rowData = (0..1).collect { row ->
240//
241//            (0..256).collect { col ->
242//                "$row - $col"
243//            }
244//
245//        }
246//
247////        try {
248//            service.exportRowWiseDataToExcelFile rowData, os, false
249////        } catch (Exception e) {
250////            e.printStackTrace()
251////            assert false
252////        } finally {
253//            os.flush()
254////            file.delete()
255////        }
256//    }
257
258    void testCSVOutput() {
259
260        // We're testing:
261        // - strings containing any newlines, comma's, or double quotes should
262        //   be surrounded with double quotes
263        // - double quotes should be escaped by double quotes ( " -> "" )
264        // - other strings and numbers should remain 'quoteless'
265        // - is the custom delimiter (e.g. tab, comma, semicolon) correctly handled
266        // - null values are exported as empty strings
267        // - possibility to use comma's as decimal separators
268        // - 2.0 -> 2 and 2.1 -> 2.1
269        // - no thousand separators
270
271        def rowData = [["""a
272b""","a,b","a\"b", "abc"],[1,2.1,"3,1"],[null,2, 2.0, 2000]]
273
274        def baos = new ByteArrayOutputStream()
275
276        service.exportRowWiseDataToCSVFile rowData, baos, '\t'
277        assertEquals 'CSV Output', '"a\nb"\t"a,b"\t"a""b"\tabc\n1\t2.1\t"3,1"\n\t2\t2\t2000', baos.toString()
278
279        baos.reset()
280
281        service.exportRowWiseDataToCSVFile rowData, baos, ','
282        assertEquals 'CSV Output', '"a\nb","a,b","a""b",abc\n1,2.1,"3,1"\n,2,2,2000', baos.toString()
283
284        baos.reset()
285
286        service.exportRowWiseDataToCSVFile rowData, baos, ';', java.util.Locale.GERMAN
287        assertEquals 'CSV Output', '"a\nb";"a,b";"a""b";abc\n1;2,1;"3,1"\n;2;2;2000', baos.toString()
288
289
290    }
291}
Note: See TracBrowser for help on using the repository browser.