Hide keyboard shortcuts

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 

2 

3""" 

4camcops_server/tasks/tests/apeq_cpft_perinatal_tests.py 

5 

6=============================================================================== 

7 

8 Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com). 

9 

10 This file is part of CamCOPS. 

11 

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. 

16 

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. 

21 

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/>. 

24 

25=============================================================================== 

26 

27""" 

28 

29from typing import Generator, Optional 

30 

31import pendulum 

32 

33from camcops_server.cc_modules.cc_unittest import DemoDatabaseTestCase 

34from camcops_server.tasks.apeq_cpft_perinatal import ( 

35 APEQCPFTPerinatal, 

36 APEQCPFTPerinatalReport, 

37) 

38 

39 

40# ============================================================================= 

41# Unit tests 

42# ============================================================================= 

43 

44class APEQCPFTPerinatalReportTestCase(DemoDatabaseTestCase): 

45 COL_Q = 0 

46 COL_TOTAL = 1 

47 COL_RESPONSE_START = 2 

48 

49 COL_FF_WHY = 1 

50 

51 def __init__(self, *args, **kwargs) -> None: 

52 super().__init__(*args, **kwargs) 

53 self.id_sequence = self.get_id() 

54 

55 def setUp(self) -> None: 

56 super().setUp() 

57 

58 self.report = APEQCPFTPerinatalReport() 

59 

60 # Really only needed for tests 

61 self.report.start_datetime = None 

62 self.report.end_datetime = None 

63 

64 @staticmethod 

65 def get_id() -> Generator[int, None, None]: 

66 i = 1 

67 

68 while True: 

69 yield i 

70 i += 1 

71 

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 

95 

96 if era is not None: 

97 task.when_created = pendulum.parse(era) 

98 

99 self.dbsession.add(task) 

100 

101 

102class APEQCPFTPerinatalReportTests(APEQCPFTPerinatalReportTestCase): 

103 def create_tasks(self) -> None: 

104 """ 

105 Creates 20 tasks. 

106 Should give us: 

107 

108 .. code-block:: none 

109 

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% 

131 

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") 

140 

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") 

146 

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") 

152 

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") 

158 

159 self.dbsession.commit() 

160 

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 ] 

170 

171 main_rows = self.report._get_main_rows(self.req) 

172 

173 # MySQL does floating point division 

174 for row, expected in zip(main_rows, expected_percentages): 

175 percentages = [] 

176 

177 for p in row[1:]: 

178 if p != "": 

179 p = int(float(p)) 

180 

181 percentages.append(p) 

182 

183 self.assertEqual(percentages, expected) 

184 

185 def test_main_rows_formatted(self) -> None: 

186 expected_q1 = [20, "50.0%", "25.0%", "25.0%"] 

187 

188 main_rows = self.report._get_main_rows( 

189 self.req, cell_format="{0:.1f}%" 

190 ) 

191 

192 self.assertEqual(main_rows[0][1:], expected_q1) 

193 

194 def test_ff_rows_contain_percentages(self) -> None: 

195 expected_ff = [20, 25, 10, 15, 10, 5, 35] 

196 

197 ff_rows = self.report._get_ff_rows(self.req) 

198 

199 # MySQL does floating point division 

200 percentages = [int(float(p)) for p in ff_rows[0][1:]] 

201 

202 self.assertEqual(percentages, expected_ff) 

203 

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%"] 

207 

208 ff_rows = self.report._get_ff_rows(self.req, cell_format="{0:.1f}%") 

209 

210 self.assertEqual(ff_rows[0][1:], expected_ff) 

211 

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 ] 

223 

224 ff_why_rows = self.report._get_ff_why_rows(self.req) 

225 

226 self.assertEqual(ff_why_rows, expected_reasons) 

227 

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) 

234 

235 

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() 

259 

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" 

263 

264 rows = self.report._get_main_rows(self.req, cell_format="{0:.1f}%") 

265 q1_row = rows[0] 

266 

267 # There should be three tasks included in the calculation. 

268 self.assertEqual(q1_row[self.COL_TOTAL], 3) 

269 

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%") 

274 

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" 

278 

279 rows = self.report._get_ff_rows(self.req, cell_format="{0:.1f}%") 

280 ff_row = rows[0] 

281 

282 # There should be three tasks included in the calculation. 

283 self.assertEqual(ff_row[self.COL_TOTAL], 3) 

284 

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%") 

289 

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" 

293 

294 rows = self.report._get_ff_why_rows(self.req) 

295 self.assertEqual(len(rows), 3) 

296 

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") 

300 

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" 

304 

305 comments = self.report._get_comments(self.req) 

306 self.assertEqual(len(comments), 3) 

307 

308 self.assertEqual(comments[0], "comments 2") 

309 self.assertEqual(comments[1], "comments 3") 

310 self.assertEqual(comments[2], "comments 4")