class SMClientTestCase(TestCase): @classmethod def setUpTestData(self): # Read SurveyMonkey API Token & Key SURVEYMONKEY_API_TOKEN = os.environ.get('SURVEYMONKEY_API_TOKEN') SURVEYMONKEY_API_KEY = os.environ.get('SURVEYMONKEY_API_KEY') self.api_client = SurveyMonkeyClient(SURVEYMONKEY_API_TOKEN, SURVEYMONKEY_API_KEY) # Create a survey and connect to SurveyMonkey via client self.survey_name = "Mike Test - DO NOT USE" def tearDown(self): # Add a second wait in between each test # To prevent running over API quota time.sleep(1) def test_get_survey_list(self): ''' Test that the client will return a list of dict containing survey IDs matching Mike Test - DO NOT USE ''' survey_list = self.api_client.get_survey_list(self.survey_name) expected = [{u'survey_id': u'72140246'}] self.assertEqual(survey_list, expected) def test_get_survey_id(self): ''' The client should return only one single ID for Mike Test - DO NOT USE ''' survey_id = self.api_client.get_survey_id(self.survey_name) self.assertEqual(survey_id, u'72140246') def test_get_survey_details(self): survey_pages = self.api_client.get_survey_details(self.survey_name) # survey_pages is a list self.assertTrue(isinstance(survey_pages, list)) # There is only 1 element/page self.assertEqual(len(survey_pages), 1) # Check each element of pages to make sure they contain the correct keys expected_page_keys = [u'position', u'sub_heading', u'page_id', u'heading', u'questions'] for p in survey_pages: self.assertEqual(p.keys(), expected_page_keys) def test_get_respondent_list(self): respondent_ids = self.api_client.get_respondent_list(self.survey_name) expected = [u'4352787778', u'4352787305', u'4352786821', u'4352786417', u'4352785923'] self.assertEqual(respondent_ids, expected) def test_get_responses(self): responses = self.api_client.get_responses(self.survey_name) # Check Respondent IDs respondent_ids = [r['respondent_id'] for r in responses] expected_resp_ids = [u'4352787778', u'4352787305', u'4352786821', u'4352786417', u'4352785923'] self.assertEqual(respondent_ids, expected_resp_ids)
def setUpTestData(self): # Read SurveyMonkey API Token & Key SURVEYMONKEY_API_TOKEN = os.environ.get('SURVEYMONKEY_API_TOKEN') SURVEYMONKEY_API_KEY = os.environ.get('SURVEYMONKEY_API_KEY') self.api_client = SurveyMonkeyClient(SURVEYMONKEY_API_TOKEN, SURVEYMONKEY_API_KEY) # Create a survey and connect to SurveyMonkey via client self.survey_name = "Mike Test - DO NOT USE"
def update_details(self): ''' Connects to SurveyMonkey API using known credentials and create or update questions & choices in db based on details obtained from get_survey_details API call ''' SURVEYMONKEY_API_TOKEN = os.environ.get('SURVEYMONKEY_API_TOKEN') SURVEYMONKEY_API_KEY = os.environ.get('SURVEYMONKEY_API_KEY') client = SurveyMonkeyClient(SURVEYMONKEY_API_TOKEN, SURVEYMONKEY_API_KEY) try: pages = client.get_survey_details(self.name) except IndexError: self.error_message = "Could not find survey in SurveyMonkey. Are you sure the survey name is correct?" else: # Clear error_message self.error_message = None for p in pages: for q in p["questions"]: # Skip if it's descriptive text if q["type"]["subtype"] != "descriptive_text": qid = q["question_id"] question, created = Question.objects.get_or_create(sm_id=qid, survey_id=self.id) question.text = q["heading"] question.survey_id = self.id if q["type"]["family"] == u'open_ended': question.open_ended = True question.save() # Update question choices as well for a in q['answers']: # Skip if no content in text if a["text"]: cid = a["answer_id"] text = a["text"] weight = a.get("weight") # TODO Allow change of choice text without # creating a new choice when choice, created = Choice.objects.get_or_create( sm_id=cid, text=text, weight=weight, question_id=question.id )
def download_responses(self): ''' Use get_responses() method in SurveyMonkeyClient to retrieve a list of response dicts, then get_or_create Respondent and Answer associated with the survey You should always call update_details() before download_responses() to avoid having non-existent Questions for survey that has never been updated previously ''' SURVEYMONKEY_API_TOKEN = os.environ.get('SURVEYMONKEY_API_TOKEN') SURVEYMONKEY_API_KEY = os.environ.get('SURVEYMONKEY_API_KEY') client = SurveyMonkeyClient(SURVEYMONKEY_API_TOKEN, SURVEYMONKEY_API_KEY) try: data = client.get_responses(self.name) except IndexError: self.error_message = "Could not find survey in SurveyMonkey. Are you sure the survey name is correct?" else: self.error_message = None for r in data: rid = r["respondent_id"] respondent, created = Respondent.objects.get_or_create(sm_id=rid, survey_id=self.id) # Only update Answer/Comment/Rating if it's a new respondent # TODO This means that if a respondent somehow update # their answers after submission, the updated value will not be reflected # unless we create a manual override here if created: for q in r["questions"]: # In each dict q there are 2 keys: "answers", and "question_id" # First, use "question_id" to locate the question text qid = q["question_id"] question = self.question_set.get(sm_id=qid, survey_id=self.id) # Associate the question with the respondent if # the question is not in the set yet if not respondent.questions.filter(id=question.id).exists(): respondent.questions.add(question) # Next, find the response for this question # q["answers"] is a list of dicts for raw_answer in q["answers"]: # Here's the tricky part, in the raw_answer dict # Sometimes results come with "col", "row", or "text" # If "text" exists, that's a dead giveaway that it's an open-ended question # We can save that as comment if "text" in raw_answer.keys(): comment, created = Answer.objects.get_or_create( question_id=question.id, respondent_id=respondent.id, text=raw_answer["text"] ) else: # A quant response # There will be "row" and "col" # Use these to look up for responses row_id = raw_answer.get("row") col_id = raw_answer.get("col") # If col_ans exists, it's a horizontal question if col_id: choice = question.choice_set.get(sm_id=col_id) else: # Try looking up with row_id choice = question.choice_set.get(sm_id=row_id) rating, created = Answer.objects.get_or_create( question_id=question.id, choice_id=choice.id, respondent_id=respondent.id, )