diff options
| author | Aurélien Warnon <awa@odoo.com> | 2019-02-06 09:29:37 +0000 |
|---|---|---|
| committer | Aurélien Warnon <awa@odoo.com> | 2019-02-06 10:34:40 +0000 |
| commit | afb1abbb60e5cdc4f76ab7b5a1b54b5e8a9283d5 (patch) | |
| tree | 351e5ef81e76689378b77739af1adfe0b1efcd02 /addons/survey/tests/test_certification_flow.py | |
| parent | dba478332681dd21a39c4a183c002b1cf6e046d2 (diff) | |
[IMP] survey: scoring & certification
Task #1902306
Purpose
=======
This commit adds certification capabilities to the survey module.
A certification is a survey with the "certification" flag set to true than can be linked
to a certification email template that contains a certification document (PDF).
This template can be edited by the user in the technical settings to customize the certification email/document.
To be able to implement this certification concept, we also have to add scoring mechanisms to surveys.
survey.questions of type 'simple_choice' and 'multiple_choice' now have scores for the suggested answers.
These question scores allow to compute a global score that is used to determine whether the user has successfully
passed the certification or not.
As additional features, we also have:
- A time limit with an interface timer that limits the test to X minutes
When reached, the survey is automatically submitted and unregistered (= unsubmitted) answers are not taken into account.
- A limited number of attempts for the survey/certification
If reached, the user can't take the survey/certification anymore
The 'survey result' layout was adapted accordingly to show the success rate of participants and the correct answers
to the survey questions.
Specs
=======
- Create a new survey :
- Add a description field for the survey
- Options on a survey :
- Passing score : (sum of all good answers) in %
- If No scoring => No passing score, no certificate
- If Scoring with answers => Passing score and can see the answers (can create certificate)
- If Scoring without answers => Passing score but can't review the answers at the end (can create certificate)
- for the questions, if "no scoring" selected, can 't see the option "good answer" and "score" on the questions
- If the 2 others options, can see the options "good answer" and "score" on the questions
- all the types of questions are available for each option.
- Questions
- Add the option correct answer on the multiples questions (one or more good answers)
- Certifications
- If scoring, force "mandatory" for "mutliple choices (1or multiple answers)"
- On the dashboard => visual information that this specific survey is a certification
- Time Limit : The student is informed on the home screen of the survey of the time limit.
The clock start when he clicks on "start survey"
- Template of the certificate : send email with attachment PDF
- Front-end :
- Add some margin
- Replace "Back to survey" with the blue-bar from the portal
- Add a timer (start when the survey starts)
- Add a progress bar (number of section and number of question inside the section)
- Analyse of the results :
- First a global graph with the number of people who''ve participated and passed the test
- Stages of a survey :
- Remove the stage "Permanent"
- 3 stages :
- draft : not on-line but can be tested (with phantom token)
- In progress : on-line
- closed : not on-line
- Who can test a survey : the manager and the user. Add this condition to the phantom token.
Diffstat (limited to 'addons/survey/tests/test_certification_flow.py')
| -rw-r--r-- | addons/survey/tests/test_certification_flow.py | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/addons/survey/tests/test_certification_flow.py b/addons/survey/tests/test_certification_flow.py new file mode 100644 index 00000000000..e596e34fa7d --- /dev/null +++ b/addons/survey/tests/test_certification_flow.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from unittest.mock import patch + +from odoo.addons.base.models.ir_mail_server import IrMailServer +from odoo.addons.survey.tests import common +from odoo.tests import tagged +from odoo.tests.common import HttpCase + + +@tagged('functional') +class TestCertificationFlow(common.SurveyCase, HttpCase): + def _answer_question(self, question, answer, answer_token, csrf_token, button_submit='next'): + # Employee submits the question answer + post_data = self._format_submission_data(question, answer, {'csrf_token': csrf_token, 'token': answer_token, 'button_submit': button_submit}) + response = self._access_submit(question.survey_id, answer_token, post_data) + self.assertResponse(response, 200) + + # Employee is redirected on next question + response = self._access_page(question.survey_id, answer_token) + self.assertResponse(response, 200) + + def _format_submission_data(self, question, answer, additional_post_data): + post_data = {} + post_data['question_id'] = question.id + if question.question_type == 'multiple_choice': + values = answer + for value in values: + key = "%s_%s_%s" % (question.survey_id.id, question.id, value) + post_data[key] = value + else: + key = "%s_%s" % (question.survey_id.id, question.id) + post_data[key] = answer + post_data.update(**additional_post_data) + return post_data + + def test_flow_certificate(self): + # Step: survey user creates the certification + # -------------------------------------------------- + with self.sudo(self.survey_user): + certification = self.env['survey.survey'].create({ + 'title': 'User Certification for SO lines', + 'access_mode': 'public', + 'users_login_required': True, + 'questions_layout': 'page_per_question', + 'users_can_go_back': True, + 'scoring_type': 'scoring_with_answers', + 'passing_score': 85.0, + 'certificate': True, + 'certification_mail_template_id': self.env.ref('survey.mail_template_certification').id, + 'is_time_limited': True, + 'time_limit': 10, + 'stage_id': self.env['survey.stage'].search([('closed', '=', False)]).id + }) + + q01 = self._add_question( + None, 'When do you know it\'s the right time to use the SO line model?', 'simple_choice', + sequence=1, + constr_mandatory=True, constr_error_msg='Please select an answer', survey_id=certification.id, + labels=[ + {'value': 'Please stop'}, + {'value': 'Only on the SO form'}, + {'value': 'Only on the Survey form'}, + {'value': 'Easy, all the time!!!', 'is_correct': True, 'answer_score': 2.0} + ]) + + q02 = self._add_question( + None, 'On average, how many lines of code do you need when you use SO line widgets?', 'simple_choice', + sequence=2, + constr_mandatory=True, constr_error_msg='Please select an answer', survey_id=certification.id, + labels=[ + {'value': '1'}, + {'value': '5', 'is_correct': True, 'answer_score': 2.0}, + {'value': '100'}, + {'value': '1000'} + ]) + + q03 = self._add_question( + None, 'What do you think about SO line widgets (not rated)?', 'free_text', + sequence=3, + constr_mandatory=True, constr_error_msg='Please tell us what you think', survey_id=certification.id) + + q04 = self._add_question( + None, 'On a scale of 1 to 10, how much do you like SO line widgets (not rated)?', 'simple_choice', + sequence=4, + constr_mandatory=True, constr_error_msg='Please tell us what you think', survey_id=certification.id, + labels=[ + {'value': '-1'}, + {'value': '0'}, + {'value': '100'} + ]) + + q05 = self._add_question( + None, 'Select all the correct "types" of SO lines', 'multiple_choice', + sequence=5, + constr_mandatory=False, survey_id=certification.id, + labels=[ + {'value': 'sale_order', 'is_correct': True, 'answer_score': 1.0}, + {'value': 'survey_page', 'is_correct': True, 'answer_score': 1.0}, + {'value': 'survey_question', 'is_correct': True, 'answer_score': 1.0}, + {'value': 'a_future_and_yet_unknown_model', 'is_correct': True, 'answer_score': 1.0}, + {'value': 'none', 'answer_score': -1.0} + ]) + + # Step: employee takes the certification + # -------------------------------------------------- + self.authenticate('user_emp', 'user_emp') + + # Employee opens start page + response = self._access_start(certification) + self.assertResponse(response, 200, [certification.title, 'Time limit for this survey', '10 minutes']) + + # -> this should have generated a new user_input with a token + user_inputs = self.env['survey.user_input'].search([('survey_id', '=', certification.id)]) + self.assertEqual(len(user_inputs), 1) + self.assertEqual(user_inputs.partner_id, self.user_emp.partner_id) + answer_token = user_inputs.token + + # Employee begins survey with first page + response = self._access_page(certification, answer_token) + self.assertResponse(response, 200) + csrf_token = self._find_csrf_token(response.text) + + with patch.object(IrMailServer, 'connect'): + self._answer_question(q01, q01.labels_ids.ids[3], answer_token, csrf_token) + self._answer_question(q02, q02.labels_ids.ids[1], answer_token, csrf_token) + self._answer_question(q03, "I think they're great!", answer_token, csrf_token) + self._answer_question(q04, q04.labels_ids.ids[0], answer_token, csrf_token, button_submit='previous') + self._answer_question(q03, "Just kidding, I don't like it...", answer_token, csrf_token) + self._answer_question(q04, q04.labels_ids.ids[0], answer_token, csrf_token) + self._answer_question(q05, [q05.labels_ids.ids[0], q05.labels_ids.ids[1], q05.labels_ids.ids[3]], answer_token, csrf_token) + + user_inputs.invalidate_cache() + # Check that certification is successfully passed + self.assertEqual(user_inputs.quizz_score, 87.5) + self.assertTrue(user_inputs.quizz_passed) + + # Check answer correction is taken into account + self.assertNotIn("I think they're great!", user_inputs.mapped('user_input_line_ids.value_free_text')) + self.assertIn("Just kidding, I don't like it...", user_inputs.mapped('user_input_line_ids.value_free_text')) + + certification_email = self.env['mail.mail'].search([], limit=1, order="create_date desc") + # Check certification email correctly sent and contains document + self.assertIn("User Certification for SO lines", certification_email.subject) + self.assertIn("employee@example.com", certification_email.email_to) + self.assertEqual(len(certification_email.attachment_ids), 1) + self.assertEqual(certification_email.attachment_ids[0].name, 'Certification Document.html') |
