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

1"""

2 camcops_server/tasks/tests/apeq_cpft_perinatal_tests.py

3

4===============================================================================

5

6 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.

7 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).

8

9 This file is part of CamCOPS.

10

11 CamCOPS is free software: you can redistribute it and/or modify

12 it under the terms of the GNU General Public License as published by

13 the Free Software Foundation, either version 3 of the License, or

14 (at your option) any later version.

15

16 CamCOPS is distributed in the hope that it will be useful,

17 but WITHOUT ANY WARRANTY; without even the implied warranty of

18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

19 GNU General Public License for more details.

20

21 You should have received a copy of the GNU General Public License

22 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.

23

24===============================================================================

25

26"""

27

28 import pendulum

29

30 from camcops_server.cc_modules.cc_unittest import DemoRequestTestCase

31 from camcops_server.tasks.apeq_cpft_perinatal import (

32 APEQCPFTPerinatalReport,

33)

34 from camcops_server.tasks.tests.factories import APEQCPFTPerinatalFactory

35

36# =============================================================================

37# Unit tests

38# =============================================================================

39

40

41 class APEQCPFTPerinatalReportTestCase(DemoRequestTestCase):

42 COL_Q = 0

43 COL_TOTAL = 1

44 COL_RESPONSE_START = 2

45

46 COL_FF_WHY = 1

47

48 def setUp(self) -> None:

49 super().setUp()

50

51 self.report = APEQCPFTPerinatalReport()

52

53 # Really only needed for tests

54 self.report.start_datetime = None

55 self.report.end_datetime = None

56

57

58 class APEQCPFTPerinatalReportTests(APEQCPFTPerinatalReportTestCase):

59 def setUp(self) -> None:

60 """

61 Creates 20 tasks.

62 Should give us:

63

64 .. code-block:: none

65

66 q1: 0 - 50%,

67 1 - 25%

68 2 - 25%

69 q2: 1 - 100%

70 q3: 0 - 5%

71 1 - 20%

72 2 - 75%

73 q4: 0 - 10%

74 1 - 40%

75 2 - 50%

76 q5: 0 - 15%

77 1 - 55%

78 2 - 30%

79 q6: 1 - 50%

80 2 - 50%

81 ff: 0 - 25%

82 1 - 10%

83 2 - 15%

84 3 - 10%

85 4 - 5%

86 5 - 35%

87

88 """

89 super().setUp()

90

91 APEQCPFTPerinatalFactory(

92 q1=0, q2=1, q3=0, q4=0, q5=2, q6=2, ff_rating=5, ff_why="ff_5_1"

93 )

94 APEQCPFTPerinatalFactory(

95 q1=0,

96 q2=1,

97 q3=1,

98 q4=0,

99 q5=2,

100 q6=2,

101 ff_rating=5,

102 ff_why="ff_5_2",

103 comments="comments_2",

104 )

105 APEQCPFTPerinatalFactory(

106 q1=0, q2=1, q3=1, q4=1, q5=2, q6=2, ff_rating=5

107 )

108 APEQCPFTPerinatalFactory(

109 q1=0, q2=1, q3=1, q4=1, q5=2, q6=2, ff_rating=5

110 )

111 APEQCPFTPerinatalFactory(

112 q1=0,

113 q2=1,

114 q3=1,

115 q4=1,

116 q5=2,

117 q6=2,

118 ff_rating=5,

119 comments="comments_5",

120 )

121

122 APEQCPFTPerinatalFactory(

123 q1=0, q2=1, q3=2, q4=1, q5=2, q6=2, ff_rating=5

124 )

125 APEQCPFTPerinatalFactory(

126 q1=0, q2=1, q3=2, q4=1, q5=1, q6=2, ff_rating=5

127 )

128 APEQCPFTPerinatalFactory(

129 q1=0, q2=1, q3=2, q4=1, q5=1, q6=2, ff_rating=4, ff_why="ff_4_1"

130 )

131 APEQCPFTPerinatalFactory(

132 q1=0, q2=1, q3=2, q4=1, q5=1, q6=2, ff_rating=3

133 )

134 APEQCPFTPerinatalFactory(

135 q1=0, q2=1, q3=2, q4=1, q5=1, q6=1, ff_rating=3, ff_why="ff_3_1"

136 )

137

138 APEQCPFTPerinatalFactory(

139 q1=1, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=2, ff_why="ff_2_1"

140 )

141 APEQCPFTPerinatalFactory(

142 q1=1, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=2

143 )

144 APEQCPFTPerinatalFactory(

145 q1=1, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=2, ff_why="ff_2_2"

146 )

147 APEQCPFTPerinatalFactory(

148 q1=1, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=1, ff_why="ff_1_1"

149 )

150 APEQCPFTPerinatalFactory(

151 q1=1, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=1, ff_why="ff_1_2"

152 )

153

154 APEQCPFTPerinatalFactory(

155 q1=2, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=0

156 )

157 APEQCPFTPerinatalFactory(

158 q1=2, q2=1, q3=2, q4=2, q5=1, q6=1, ff_rating=0

159 )

160 APEQCPFTPerinatalFactory(

161 q1=2, q2=1, q3=2, q4=2, q5=0, q6=None, ff_rating=0

162 )

163 APEQCPFTPerinatalFactory(

164 q1=2, q2=1, q3=2, q4=2, q5=0, q6=None, ff_rating=0

165 )

166 APEQCPFTPerinatalFactory(

167 q1=2,

168 q2=1,

169 q3=2,

170 q4=2,

171 q5=0,

172 q6=1,

173 ff_rating=0,

174 comments="comments_20",

175 )

176

177 def test_main_rows_contain_percentages(self) -> None:

178 expected_percentages = [

179 ["20", "50", "25", "25"], # q1

180 ["20", "", "100", ""], # q2

181 ["20", "5", "20", "75"], # q3

182 ["20", "10", "40", "50"], # q4

183 ["20", "15", "55", "30"], # q5

184 ["18", "", "50", "50"], # q6

185 ]

186

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

188

189 # MySQL does floating point division

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

191 percentages = []

192

193 for p in row[1:]:

194 if p != "":

195 p = str(int(float(p)))

196

197 percentages.append(p)

198

199 self.assertEqual(percentages, expected)

200

201 def test_main_rows_formatted(self) -> None:

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

203

204 main_rows = self.report._get_main_rows(

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

206 )

207

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

209

210 def test_ff_rows_contain_percentages(self) -> None:

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

212

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

214

215 # MySQL does floating point division

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

217

218 self.assertEqual(percentages, expected_ff)

219

220 def test_ff_rows_formatted(self) -> None:

221 expected_ff = [20, "25.0%", "10.0%", "15.0%", "10.0%", "5.0%", "35.0%"]

222

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

224

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

226

227 def test_ff_why_rows_contain_reasons(self) -> None:

228 expected_reasons = [

229 ["Extremely unlikely", "ff_1_1"],

230 ["Extremely unlikely", "ff_1_2"],

231 ["Unlikely", "ff_2_1"],

232 ["Unlikely", "ff_2_2"],

233 ["Neither likely nor unlikely", "ff_3_1"],

234 ["Likely", "ff_4_1"],

235 ["Extremely likely", "ff_5_1"],

236 ["Extremely likely", "ff_5_2"],

237 ]

238

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

240

241 self.assertEqual(ff_why_rows, expected_reasons)

242

243 def test_comments(self) -> None:

244 expected_comments = ["comments_2", "comments_5", "comments_20"]

245

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

247 self.assertEqual(comments, expected_comments)

248

249

250 class APEQCPFTPerinatalReportDateRangeTests(APEQCPFTPerinatalReportTestCase):

251 def setUp(self) -> None:

252 super().setUp()

253

254 APEQCPFTPerinatalFactory(

255 q1=1,

256 q2=0,

257 q3=0,

258 q4=0,

259 q5=0,

260 q6=0,

261 ff_rating=0,

262 ff_why="ff why 1",

263 comments="comments 1",

264 when_created=pendulum.parse("2018-10-01"),

265 )

266 APEQCPFTPerinatalFactory(

267 q1=0,

268 q2=0,

269 q3=0,

270 q4=0,

271 q5=0,

272 q6=0,

273 ff_rating=2,

274 ff_why="ff why 2",

275 comments="comments 2",

276 when_created=pendulum.parse("2018-10-02"),

277 )

278 APEQCPFTPerinatalFactory(

279 q1=0,

280 q2=0,

281 q3=0,

282 q4=0,

283 q5=0,

284 q6=0,

285 ff_rating=2,

286 ff_why="ff why 3",

287 comments="comments 3",

288 when_created=pendulum.parse("2018-10-03"),

289 )

290 APEQCPFTPerinatalFactory(

291 q1=0,

292 q2=0,

293 q3=0,

294 q4=0,

295 q5=0,

296 q6=0,

297 ff_rating=2,

298 ff_why="ff why 4",

299 comments="comments 4",

300 when_created=pendulum.parse("2018-10-04"),

301 )

302 APEQCPFTPerinatalFactory(

303 q1=1,

304 q2=0,

305 q3=0,

306 q4=0,

307 q5=0,

308 q6=0,

309 ff_rating=0,

310 ff_why="ff why 5",

311 comments="comments 5",

312 when_created=pendulum.parse("2018-10-05"),

313 )

314

315 def test_main_rows_filtered_by_date(self) -> None:

316 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"

317 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"

318

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

320 q1_row = rows[0]

321

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

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

324

325 # For question 1 all of them answered 0 so we would expect

326 # 100%. If the results aren't being filtered we will get

327 # 60%

328 self.assertEqual(q1_row[self.COL_RESPONSE_START + 0], "100.0%")

329

330 def test_ff_rows_filtered_by_date(self) -> None:

331 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"

332 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"

333

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

335 ff_row = rows[0]

336

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

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

339

340 # For the ff question all of them answered 2 so we would expect

341 # 100%. If the results aren't being filtered we will get

342 # 60%

343 self.assertEqual(ff_row[self.COL_RESPONSE_START + 2], "100.0%")

344

345 def test_ff_why_row_filtered_by_date(self) -> None:

346 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"

347 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"

348

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

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

351

352 self.assertEqual(rows[0][self.COL_FF_WHY], "ff why 2")

353 self.assertEqual(rows[1][self.COL_FF_WHY], "ff why 3")

354 self.assertEqual(rows[2][self.COL_FF_WHY], "ff why 4")

355

356 def test_comments_filtered_by_date(self) -> None:

357 self.report.start_datetime = "2018-10-02T00:00:00.000000+00:00"

358 self.report.end_datetime = "2018-10-05T00:00:00.000000+00:00"

359

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

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

362

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

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

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