Coverage for tests/starters.py : 98%

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"""The start-up functions for batches of tests.
3We have divided the tests in batches.
4Each batch is a separate file.
6The batches can be run alltogether in sequential order,
7or they can be run individually.
9The `start` function achieves that when a batch is run as part of a bigger sequence,
10the initial situation for the batch is the right one.
11And also, if the batch is run individually, that it starts with exactly the same
12state.
14## Clean slate
16The base line is clean database, i.e. a database with
17all the value tables fully filled, with a set of test users,
18with packages, criteria, and types, but not with user-contributed content,
19such as contributions, assessments, and reviews.
21This is the *clean slate*.
23The starter functions may insert a few records in the database and fetch
24a few value tables for usage in test functions.
25"""
27from control.utils import pick as G
28from example import (
29 ASSESS,
30 COMMENTS,
31 COMPLETE,
32 CONTRIB,
33 CRITERIA_ENTRY,
34 CRITERIA_ENTRIES_N,
35 COUNTRY,
36 ELLIPS_DIV,
37 EVIDENCE,
38 EXPERT,
39 FINAL,
40 REVIEW,
41 REVIEW_ENTRY,
42 REVIEWER_E,
43 REVIEWER_F,
44 SCORE,
45 START_ASSESSMENT,
46 START_REVIEW,
47 SUBMIT_ASSESSMENT,
48 TYPE,
49 TYPE1,
50 TYPE2,
51 USER,
52)
53from helpers import (
54 findDetails,
55 findValues,
56 getItem,
57 getReviewEntryId,
58 getScores,
59)
60from subtest import (
61 assertAddItem,
62 assertEditor,
63 assertModifyField,
64 assertStage,
65 assertStartTask,
66 assertStatus,
67)
70def getValueTable(cl, table):
71 """Get a mapping of values in a value table to their object ids.
73 We look directly in the list of items of a valueTable.
75 The mapping is stored in the dict `dest` keyed by the
76 name of the valueTable.
78 Parameters
79 ----------
80 table: string
81 The name of a value table
83 Returns
84 -------
85 dict
86 The stored value dict for this valueTable
87 """
89 response = cl.get(f"/{table}/list")
90 text = response.get_data(as_text=True)
91 return findValues(table, text)
94def makeItem(cl, table, cId=None, aId=None):
95 """Makes a contribution/assessment/review.
97 Parameters
98 ----------
99 cl: fixture
100 table: string
101 Either `contrib` or `assessment` or `review`
102 cId: string(ObjectId), optional `None`
103 If we make an assessment, the id of the contribution for which it is an
104 assessment
105 aId: string(ObjectId), optional `None`
106 If we make a review, the id of the assessment for which it is a
107 review
109 Returns
110 -------
111 eid: string(ObjectId)
112 the id of the contribution/assessment
113 """
115 if table == CONTRIB:
116 return assertAddItem(cl, table, True)
117 if table == ASSESS:
118 return assertStartTask(cl, START_ASSESSMENT, cId, True)
119 if table == REVIEW: 119 ↛ exitline 119 didn't return from function 'makeItem', because the condition on line 119 was never false
120 return assertStartTask(cl, START_REVIEW, aId, True)
123def start(
124 clientOffice=None,
125 clientOwner=None,
126 clientExpert=None,
127 clientFinal=None,
128 users=False,
129 types=False,
130 countries=False,
131 contrib=False,
132 assessment=False,
133 fillout=False,
134 submit=False,
135 assign=False,
136 review=False,
137):
138 """The start sequence for a batch of tests.
140 The first step is to start with a clean slate inth database:
141 Only the value records, no user-contributed content.
143 It depends on the batch what we have to make on top of that..
145 The result is always that certain records in the database are retrieved,
146 of if they do not exist, created.
148 Records with user added content are stored in the dict `recordId`,
149 under the name of the table as key.
151 Records in value tables are stored in the dict `valueTables`,
152 under the name of the table as key.
154 !!! hint "Dependencies of parameters"
155 Some things are dependent on others, for example, making an assessment
156 presupposes that there is a contribution.
157 The function will switch on all parameters that are implied before
158 creating or finding stuff.
160 Parameters
161 ----------
162 clientOffice, clientOwner: fixture
163 users: boolean, optional `False`
164 Whether to fetch the list of users
165 types: boolean, optional `False`
166 Whether to fetch the list of contribution types
167 countries: boolean, optional `False`
168 Whether to fetch the list of countries
169 contrib: boolean, optional `False`
170 Whether to find or make a contribution
171 assessment: boolean, optional `False`
172 Whether to find or make an assessment
173 fillout: boolean, optional `False`
174 Whether to fill out the criteria entries
175 submit: boolean, optional `False`
176 Whether to submit the completed assessment
177 assign: boolean, optional `False`
178 Whether to assign reviewers
179 review: boolean, optional `False`
180 Whether to start and fillout both reviews
182 Returns
183 -------
184 valueTables: dict, optional `None`
185 Where the retrieved data for the value tables end up
186 recordId: dict, optional `None`
187 Where the retrieved ids for the records end up
188 ids: dict, optional `None`
189 A resulting mapping between values in a value table and their corresponding ids
190 """
192 if review:
193 assign = True
194 if assign:
195 submit = True
196 if submit:
197 fillout = True
198 if fillout:
199 assessment = True
200 if assessment:
201 contrib = True
202 types = True
203 if contrib:
204 users = True
206 valueTables = {}
207 recordId = {}
208 recordInfo = {}
209 ids = {}
211 def startReviews():
212 aId = recordId[ASSESS]
213 cIds = recordId[CRITERIA_ENTRY]
215 recordId.setdefault(REVIEW, {})
216 clr = {EXPERT: clientExpert, FINAL: clientFinal}
218 for (user, cl) in clr.items():
219 rId = makeItem(cl, REVIEW, aId=aId)
220 recordId[REVIEW][user] = rId
222 for (user, cl) in clr.items():
223 rId = recordId[REVIEW][user]
224 for (i, cId) in enumerate(cIds):
225 rEId = recordId[REVIEW][EXPERT]
226 rFId = recordId[REVIEW][FINAL]
227 reId = getReviewEntryId(clr, cId, rEId, rFId)
228 reId = reId[user]
229 newValue = [f"{user}'s comment on criteria {i + 1}"]
230 newValueRep = ",".join(newValue)
231 assertModifyField(
232 cl, REVIEW_ENTRY, reId, COMMENTS, (newValue, newValueRep), True
233 )
235 def startAssign():
236 aId = recordId[ASSESS]
237 users = G(valueTables, USER)
238 for (field, user) in ((REVIEWER_E, EXPERT), (REVIEWER_F, FINAL)):
239 value = G(users, user)
240 assertModifyField(clientOffice, ASSESS, aId, field, (value, user), True)
242 if review:
243 startReviews()
245 def startSubmit():
246 aId = recordId[ASSESS]
247 url = f"/api/task/{SUBMIT_ASSESSMENT}/{aId}"
248 assertStatus(clientOwner, url, True)
250 if assign: 250 ↛ exitline 250 didn't return from function 'startSubmit', because the condition on line 250 was never false
251 startAssign()
253 def startFillout():
254 aId = recordId[ASSESS]
255 assessInfo = getItem(clientOwner, ASSESS, aId)
256 criteriaEntries = findDetails(assessInfo["text"], CRITERIA_ENTRY)
257 nCId = len(criteriaEntries)
258 assert nCId == CRITERIA_ENTRIES_N[TYPE1]
259 cIds = []
261 for (i, (cId, material)) in enumerate(criteriaEntries):
262 cIds.append(cId)
263 assert ELLIPS_DIV in material
264 scores = getScores(cId)
265 (scoreValue, scoreId) = sorted(scores.items())[1]
266 assertModifyField(
267 clientOwner, CRITERIA_ENTRY, cId, SCORE, (scoreId, scoreValue), True,
268 )
269 theEvidence = [f"evidence for {i + 1}", "see the internet"]
270 theEvidenceRep = ",".join(theEvidence)
271 assertModifyField(
272 clientOwner,
273 CRITERIA_ENTRY,
274 cId,
275 EVIDENCE,
276 (theEvidence, theEvidenceRep),
277 True,
278 )
279 recordId[CRITERIA_ENTRY] = cIds
281 assertStage(clientOwner, ASSESS, aId, COMPLETE)
283 if submit: 283 ↛ exitline 283 didn't return from function 'startFillout', because the condition on line 283 was never false
284 startSubmit()
286 def startAssessment():
287 eid = recordId[CONTRIB]
288 assertModifyField(
289 clientOwner, CONTRIB, eid, TYPE, (ids["TYPE1"], TYPE1), True,
290 )
291 aId = makeItem(clientOwner, ASSESS, cId=eid)
292 recordId[ASSESS] = aId
293 assertEditor(clientOwner, ASSESS, aId, valueTables, True)
295 if fillout:
296 startFillout()
298 def startContrib():
299 eid = makeItem(clientOwner, CONTRIB)
300 recordId[CONTRIB] = eid
301 assertEditor(clientOwner, CONTRIB, eid, valueTables, True)
303 if assessment:
304 startAssessment()
306 if users:
307 valueTables[USER] = getValueTable(clientOffice, USER)
309 if countries:
310 valueTables[COUNTRY] = getValueTable(clientOffice, COUNTRY)
312 if types:
313 typeValues = getValueTable(clientOffice, TYPE)
314 ids["TYPE1"] = typeValues[TYPE1]
315 ids["TYPE2"] = typeValues[TYPE2]
316 valueTables[TYPE] = typeValues
318 if contrib:
319 startContrib()
321 return dict(
322 valueTables=valueTables, recordId=recordId, recordInfo=recordInfo, ids=ids
323 )