Coverage for tasks/tests/apeq_cpft_perinatal_tests.py : 22%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
3"""
4camcops_server/tasks/tests/apeq_cpft_perinatal_tests.py
6===============================================================================
8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com).
10 This file is part of CamCOPS.
12 CamCOPS is free software: you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation, either version 3 of the License, or
15 (at your option) any later version.
17 CamCOPS is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
25===============================================================================
27"""
29from typing import Generator, Optional
31import pendulum
33from camcops_server.cc_modules.cc_unittest import DemoDatabaseTestCase
34from camcops_server.tasks.apeq_cpft_perinatal import (
35 APEQCPFTPerinatal,
36 APEQCPFTPerinatalReport,
37)
40# =============================================================================
41# Unit tests
42# =============================================================================
44class APEQCPFTPerinatalReportTestCase(DemoDatabaseTestCase):
45 COL_Q = 0
46 COL_TOTAL = 1
47 COL_RESPONSE_START = 2
49 COL_FF_WHY = 1
51 def __init__(self, *args, **kwargs) -> None:
52 super().__init__(*args, **kwargs)
53 self.id_sequence = self.get_id()
55 def setUp(self) -> None:
56 super().setUp()
58 self.report = APEQCPFTPerinatalReport()
60 # Really only needed for tests
61 self.report.start_datetime = None
62 self.report.end_datetime = None
64 @staticmethod
65 def get_id() -> Generator[int, None, None]:
66 i = 1
68 while True:
69 yield i
70 i += 1
72 def create_task(self,
73 q1: Optional[int],
74 q2: Optional[int],
75 q3: Optional[int],
76 q4: Optional[int],
77 q5: Optional[int],
78 q6: Optional[int],
79 ff_rating: int,
80 ff_why: str = None,
81 comments: str = None,
82 era: str = None) -> None:
83 task = APEQCPFTPerinatal()
84 self.apply_standard_task_fields(task)
85 task.id = next(self.id_sequence)
86 task.q1 = q1
87 task.q2 = q2
88 task.q3 = q3
89 task.q4 = q4
90 task.q5 = q5
91 task.q6 = q6
92 task.ff_rating = ff_rating
93 task.ff_why = ff_why
94 task.comments = comments
96 if era is not None:
97 task.when_created = pendulum.parse(era)
99 self.dbsession.add(task)
102class APEQCPFTPerinatalReportTests(APEQCPFTPerinatalReportTestCase):
103 def create_tasks(self) -> None:
104 """
105 Creates 20 tasks.
106 Should give us:
108 .. code-block:: none
110 q1: 0 - 50%,
111 1 - 25%
112 2 - 25%
113 q2: 1 - 100%
114 q3: 0 - 5%
115 1 - 20%
116 2 - 75%
117 q4: 0 - 10%
118 1 - 40%
119 2 - 50%
120 q5: 0 - 15%
121 1 - 55%
122 2 - 30%
123 q6: 1 - 50%
124 2 - 50%
125 ff: 0 - 25%
126 1 - 10%
127 2 - 15%
128 3 - 10%
129 4 - 5%
130 5 - 35%
132 """
133 # q1 q2 q3 q4 q5 q6 ff
134 self.create_task(0, 1, 0, 0, 2, 2, 5, ff_why="ff_5_1")
135 self.create_task(0, 1, 1, 0, 2, 2, 5, ff_why="ff_5_2",
136 comments="comments_2")
137 self.create_task(0, 1, 1, 1, 2, 2, 5)
138 self.create_task(0, 1, 1, 1, 2, 2, 5)
139 self.create_task(0, 1, 1, 1, 2, 2, 5, comments="comments_5")
141 self.create_task(0, 1, 2, 1, 2, 2, 5)
142 self.create_task(0, 1, 2, 1, 1, 2, 5)
143 self.create_task(0, 1, 2, 1, 1, 2, 4, ff_why="ff_4_1")
144 self.create_task(0, 1, 2, 1, 1, 2, 3)
145 self.create_task(0, 1, 2, 1, 1, 1, 3, ff_why="ff_3_1")
147 self.create_task(1, 1, 2, 2, 1, 1, 2, ff_why="ff_2_1")
148 self.create_task(1, 1, 2, 2, 1, 1, 2)
149 self.create_task(1, 1, 2, 2, 1, 1, 2, ff_why="ff_2_2")
150 self.create_task(1, 1, 2, 2, 1, 1, 1, ff_why="ff_1_1")
151 self.create_task(1, 1, 2, 2, 1, 1, 1, ff_why="ff_1_2")
153 self.create_task(2, 1, 2, 2, 1, 1, 0)
154 self.create_task(2, 1, 2, 2, 1, 1, 0)
155 self.create_task(2, 1, 2, 2, 0, None, 0)
156 self.create_task(2, 1, 2, 2, 0, None, 0)
157 self.create_task(2, 1, 2, 2, 0, 1, 0, comments="comments_20")
159 self.dbsession.commit()
161 def test_main_rows_contain_percentages(self) -> None:
162 expected_percentages = [
163 [20, 50, 25, 25], # q1
164 [20, "", 100, ""], # q2
165 [20, 5, 20, 75], # q3
166 [20, 10, 40, 50], # q4
167 [20, 15, 55, 30], # q5
168 [18, "", 50, 50], # q6
169 ]
171 main_rows = self.report._get_main_rows(self.req)
173 # MySQL does floating point division
174 for row, expected in zip(main_rows, expected_percentages):
175 percentages = []
177 for p in row[1:]:
178 if p != "":
179 p = int(float(p))
181 percentages.append(p)
183 self.assertEqual(percentages, expected)
185 def test_main_rows_formatted(self) -> None:
186 expected_q1 = [20, "50.0%", "25.0%", "25.0%"]
188 main_rows = self.report._get_main_rows(
189 self.req, cell_format="{0:.1f}%"
190 )
192 self.assertEqual(main_rows[0][1:], expected_q1)
194 def test_ff_rows_contain_percentages(self) -> None:
195 expected_ff = [20, 25, 10, 15, 10, 5, 35]
197 ff_rows = self.report._get_ff_rows(self.req)
199 # MySQL does floating point division
200 percentages = [int(float(p)) for p in ff_rows[0][1:]]
202 self.assertEqual(percentages, expected_ff)
204 def test_ff_rows_formatted(self) -> None:
205 expected_ff = [20, "25.0%", "10.0%", "15.0%",
206 "10.0%", "5.0%", "35.0%"]
208 ff_rows = self.report._get_ff_rows(self.req, cell_format="{0:.1f}%")
210 self.assertEqual(ff_rows[0][1:], expected_ff)
212 def test_ff_why_rows_contain_reasons(self) -> None:
213 expected_reasons = [
214 ["Extremely unlikely", "ff_1_1"],
215 ["Extremely unlikely", "ff_1_2"],
216 ["Unlikely", "ff_2_1"],
217 ["Unlikely", "ff_2_2"],
218 ["Neither likely nor unlikely", "ff_3_1"],
219 ["Likely", "ff_4_1"],
220 ["Extremely likely", "ff_5_1"],
221 ["Extremely likely", "ff_5_2"],
222 ]
224 ff_why_rows = self.report._get_ff_why_rows(self.req)
226 self.assertEqual(ff_why_rows, expected_reasons)
228 def test_comments(self) -> None:
229 expected_comments = [
230 "comments_2", "comments_5", "comments_20",
231 ]
232 comments = self.report._get_comments(self.req)
233 self.assertEqual(comments, expected_comments)
236class APEQCPFTPerinatalReportDateRangeTests(APEQCPFTPerinatalReportTestCase):
237 def create_tasks(self) -> None:
238 self.create_task(1, 0, 0, 0, 0, 0, 0,
239 ff_why="ff why 1",
240 comments="comments 1",
241 era="2018-10-01T00:00:00.000000+00:00")
242 self.create_task(0, 0, 0, 0, 0, 0, 2,
243 ff_why="ff why 2",
244 comments="comments 2",
245 era="2018-10-02T00:00:00.000000+00:00")
246 self.create_task(0, 0, 0, 0, 0, 0, 2,
247 ff_why="ff why 3",
248 comments="comments 3",
249 era="2018-10-03T00:00:00.000000+00:00")
250 self.create_task(0, 0, 0, 0, 0, 0, 2,
251 ff_why="ff why 4",
252 comments="comments 4",
253 era="2018-10-04T00:00:00.000000+00:00")
254 self.create_task(1, 0, 0, 0, 0, 0, 0,
255 ff_why="ff why 5",
256 comments="comments 5",
257 era="2018-10-05T00:00:00.000000+00:00")
258 self.dbsession.commit()
260 def test_main_rows_filtered_by_date(self) -> None:
261 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"
262 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"
264 rows = self.report._get_main_rows(self.req, cell_format="{0:.1f}%")
265 q1_row = rows[0]
267 # There should be three tasks included in the calculation.
268 self.assertEqual(q1_row[self.COL_TOTAL], 3)
270 # For question 1 all of them answered 0 so we would expect
271 # 100%. If the results aren't being filtered we will get
272 # 60%
273 self.assertEqual(q1_row[self.COL_RESPONSE_START + 0], "100.0%")
275 def test_ff_rows_filtered_by_date(self) -> None:
276 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"
277 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"
279 rows = self.report._get_ff_rows(self.req, cell_format="{0:.1f}%")
280 ff_row = rows[0]
282 # There should be three tasks included in the calculation.
283 self.assertEqual(ff_row[self.COL_TOTAL], 3)
285 # For the ff question all of them answered 2 so we would expect
286 # 100%. If the results aren't being filtered we will get
287 # 60%
288 self.assertEqual(ff_row[self.COL_RESPONSE_START + 2], "100.0%")
290 def test_ff_why_row_filtered_by_date(self) -> None:
291 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"
292 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"
294 rows = self.report._get_ff_why_rows(self.req)
295 self.assertEqual(len(rows), 3)
297 self.assertEqual(rows[0][self.COL_FF_WHY], "ff why 2")
298 self.assertEqual(rows[1][self.COL_FF_WHY], "ff why 3")
299 self.assertEqual(rows[2][self.COL_FF_WHY], "ff why 4")
301 def test_comments_filtered_by_date(self) -> None:
302 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"
303 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"
305 comments = self.report._get_comments(self.req)
306 self.assertEqual(len(comments), 3)
308 self.assertEqual(comments[0], "comments 2")
309 self.assertEqual(comments[1], "comments 3")
310 self.assertEqual(comments[2], "comments 4")