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

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

Fixed only being able to export to tab delimited; fixed 'null' values in export; fixed extra period between filename and extension

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