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

Last change on this file since 1882 was 1882, checked in by s.h.sikkema@…, 6 years ago

Fixed an assayService unit test

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