.. role:: python(code) :language: python .. `project assignment app `_ `test assignment algorithm `_ `type of testing _` .. _`sec:architecture`: Practice (project assignment) ----------------------------- The goal here is to draw the contour lines of an initial project architecture on a small yet realistic topic. The context is the choice of a final year project by students. + Every student must be assigned to one project. The number of available projects is greater or equal to the number of students. + Each project has a title, at least one supervisor, a context, a number of maximum duplication meaning that this project can be assigned between zero to this maximum duplication number. + The assignments must not be challengeable by any other assignments where **all** students would be **at least as happy** than the current ones with at least one student happier. If this situation were to happen, everybody would agree to accept the other assignments, the original solution would be qualified as **unstable**. The users are the supervisors who propose some projects, the students who submit choices and the administrator who runs the assignment once the projects and choices are collected. .. admonition:: Exercise (easy) There is not a single answer to the following questions, it is usually either a question of compromise or even conventions. 1. How would you imagine broadly the different features of such an app from a user perspective? (try to think about tasks as uncoupled / isolated as possible) 2. It is not plausible to try to build the whole app directly. Let's postpone the decision on the user interfaces (probably web) to avoid tying up our architecture to a specific solution. The goal is to be able to test and possibly substitute components as seamlessly as possible. To start somewhere, what would be the **minimal core logic around the project assignment** step? Why is it interesting to start there? .. _`ex:assignement_app`: .. collapse:: Correction 1. The students: + log in the app + obtain the project catalog + submit their ranking list + check their submitted ranking list + consult their assignment on one project The supervisors: + log in the app + obtain the project catalog + post a project + edit a project that they posted + remove a project that they posted + consult the assignment of all their projects The administrator: + log in the app + obtain the ranking lists + obtain the project catalog + generate the best assignment list 2. From the project catalog and all the ranking lists, generate a suitable assignment list. This step does not care about: + how the ranking lists or the project catalog were assembled. + how the assignment is requested (CLI, web, etc). + 'what' is assigned to 'what', students to projects, candidates to jobs, drivers to cars, etc. Only the notion of ranking is important there. For every student, try to assign his favorite project. If the project is available, assign the project to the student, otherwise, move to the next preferred project until one available is assigned. Since it might be useful to compare two potential assignments, a student satisfaction score would be useful based on the rank of the assigned project in the choice rankings. .. _`fig:assign`: .. figure:: assign.png :width: 300 :alt: Project assignment graph Project assignment graph .. admonition:: Exercise (intermediate) 1. What structure would be appropriate to represent all student choices, assignments and scores? 2. Define some unit tests and implement them. 3. Implement the assign logic and test it. Do not attempt to test the solution stability. .. _`ex:assignment_algo`: .. collapse:: Correction 1. all student choices: A dict of lists ``{chooser: [choices from least to most preferred]}`` to be able to drop tested preferred choices in constant time. assignments: A dict ``{choice: chooser}`` to be able to check in constant time "if the project is already assigned to another student". scores: A dict ``{chooser: score}`` to be able to compare in constant time two satisfaction scores from a student. 2. + the number of students has to be lower or equal to the number of projects otherwise an exception is raised + several small examples can be imagined (2 students, 2 projects; 2 students, 3 projects; etc) .. literalinclude:: ../../../../tests/tools_methods/testing/test_assignment.py :pyobject: test_validate :name: test_validate :linenos: :caption: tests .. literalinclude:: ../../../../tests/tools_methods/testing/test_assignment.py :pyobject: test_assign :name: test_assign :linenos: :caption: tests 3. .. literalinclude:: ../../../../src/tools_methods/testing/assignment.py :lines: 4-51 :name: assign :linenos: :caption: src .. admonition:: Exercise (easy) Give one example of what would constitute here: 1. integration testing 2. performance/stress testing 3. acceptance/functional testing .. _`ex:type_tests`: .. collapse:: Correction 1. Several other modules will be required to implement all the features imagined before. + ``rankings`` for example for ranking list validation, edition + ``projects`` for example for project validation, edition + ``database`` for the permanence: reading / writing In these interactions, it is probable that the first two will require the third. Testing that a valid ranking list is correctly stored it in database would be a required integration test. 2. The important performances here might be: + can the app interface handle the load when every student try to submit their rankings at the same time at the very last minute? + can the assignment strategy handle the expected number of students in a reasonable time? 3. + can a supervisor (and not a student) insert in the project catalog? + can a student modify his rankings (and no one else)?