Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_RedcapConnector.py 8.25 KiB
# coding=utf-8

import logging

from django.test import TestCase

from functions import create_study_subject, prepare_test_redcap_connection
from web.models import Language
from web.models.inconsistent_subject import InconsistentSubject
from web.models.missing_subject import MissingSubject
from web.redcap_connector import RedcapConnector, RedcapSubject, different_string
from web.views.notifications import get_today_midnight_date

logger = logging.getLogger(__name__)


class TestRedcapConnector(TestCase):
    def test_invalid_configuration(self):
        redcap_connection = RedcapConnector()
        self.assertFalse(redcap_connection.is_valid())

    def test_valid_configuration(self):
        prepare_test_redcap_connection()

        redcap_connection = RedcapConnector()
        self.assertTrue(redcap_connection.is_valid())

    def test_get_invalid_connections(self):
        prepare_test_redcap_connection()

        redcap_connection = RedcapConnector()
        data = redcap_connection.find_missing()
        self.assertTrue(len(data) > 0)
        missing_subject = data[0]
        self.assertIsNone(missing_subject.subject)
        self.assertIsNotNone(missing_subject.redcap_id)
        self.assertIsNotNone(missing_subject.redcap_url)
        self.assertFalse(missing_subject.ignore)

    def test_get_invalid_connections_for_new_local(self):
        prepare_test_redcap_connection()
        subject = create_study_subject()
        subject.nd_number = "123"
        subject.save()

        redcap_connection = RedcapConnector()
        data = redcap_connection.find_missing()
        self.assertTrue(len(data) > 0)

    def test_get_inconsistent_data(self):
        prepare_test_redcap_connection()
        subject = create_study_subject()
        # noinspection SpellCheckingInspection
        subject.nd_number = 'NDtest_external'
        subject.save()

        redcap_connection = RedcapConnector()
        data = redcap_connection.find_inconsistent()
        self.assertTrue(len(data) > 0)
        inconsistent_subject = data[0]
        self.assertIsNotNone(inconsistent_subject.subject)
        self.assertTrue(len(inconsistent_subject.fields))

    def test_get_red_cap_subjects(self):
        prepare_test_redcap_connection()
        redcap_connection = RedcapConnector()
        data = redcap_connection.get_red_cap_subjects()
        nd_numbers = {}
        for row in data:
            self.assertIsNone(nd_numbers.get(row.nd_number), "RED Cap subject duplicated: " + row.nd_number)
            nd_numbers[row.nd_number] = row

    def test_create_inconsistent_data_for_date_born(self):
        prepare_test_redcap_connection()
        study_subject = create_study_subject()

        redcap_subject = self.create_redcap_subject_from_smash_subject(study_subject)
        study_subject.subject.date_born = get_today_midnight_date()

        self.check_single_inconsistency(redcap_subject, study_subject)

    def check_single_inconsistency(self, redcap_subject, study_subject):
        redcap_connection = RedcapConnector()
        result = redcap_connection.create_inconsistency_subject(redcap_subject, study_subject, "")
        self.assertIsNotNone(result)
        self.assertEqual(1, len(result.fields), "Invalid number of fields. Found: " + str(result.fields))

    def test_create_inconsistent_data_for_dead(self):
        prepare_test_redcap_connection()
        study_subject = create_study_subject()

        redcap_subject = self.create_redcap_subject_from_smash_subject(study_subject)
        study_subject.subject.dead = not study_subject.subject.dead

        self.check_single_inconsistency(redcap_subject, study_subject)

    def test_create_inconsistent_data_for_language(self):
        language = Language.objects.create(name="xx")
        language.save()
        prepare_test_redcap_connection()
        study_subject = create_study_subject()

        redcap_subject = self.create_redcap_subject_from_smash_subject(study_subject)
        study_subject.subject.languages.add(language)

        self.check_single_inconsistency(redcap_subject, study_subject)

    def test_create_inconsistent_data_for_language2(self):
        language = Language.objects.create(name="xx")
        prepare_test_redcap_connection()
        subject = create_study_subject()

        redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
        redcap_subject.add_language(language)

        self.check_single_inconsistency(redcap_subject, subject)

    def test_create_inconsistent_data_for_mpower_id(self):
        prepare_test_redcap_connection()
        subject = create_study_subject()

        redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
        subject.mpower_id = "105"

        self.check_single_inconsistency(redcap_subject, subject)

    def test_create_inconsistent_data_for_mpower_id_with_whitespace(self):
        prepare_test_redcap_connection()
        subject = create_study_subject()
        subject.mpower_id = "105"

        redcap_subject = self.create_redcap_subject_from_smash_subject(subject)
        subject.mpower_id = " 105   "

        redcap_connection = RedcapConnector()
        result = redcap_connection.create_inconsistency_subject(redcap_subject, subject, "")
        self.assertIsNone(result)

    @staticmethod
    def create_redcap_subject_from_smash_subject(study_subject):
        redcap_subject = RedcapSubject()
        for language in study_subject.subject.languages.all():
            redcap_subject.add_language(language)
        redcap_subject.mpower_id = study_subject.mpower_id
        redcap_subject.dead = study_subject.subject.dead
        redcap_subject.date_born = study_subject.subject.date_born
        redcap_subject.nd_number = study_subject.nd_number
        redcap_subject.sex = study_subject.subject.sex
        return redcap_subject

    def test_get_language(self):
        language = Language.objects.create(name="xx")
        language.save()
        prepare_test_redcap_connection()

        redcap_connection = RedcapConnector()

        self.assertIsNotNone(redcap_connection.get_language("xx"))
        self.assertIsNone(redcap_connection.get_language("yy"))

    def test_refresh_missing(self):
        prepare_test_redcap_connection()

        redcap_connection = RedcapConnector()
        redcap_connection.refresh_missing()
        count = MissingSubject.objects.count()
        self.assertTrue(count > 0)

        for missing in MissingSubject.objects.all():
            missing.ignore = True
            missing.save()

        redcap_connection.refresh_missing()
        count2 = MissingSubject.objects.count()

        self.assertEqual(count, count2)

    def test_refresh_missing_remove_old(self):
        missing = MissingSubject.objects.create()
        missing.ignore = False
        missing.save()
        prepare_test_redcap_connection()

        self.assertEqual(MissingSubject.objects.filter(id=missing.id).count(), 1)

        redcap_connection = RedcapConnector()
        redcap_connection.refresh_missing()
        self.assertTrue(MissingSubject.objects.count() > 0)
        self.assertEqual(MissingSubject.objects.filter(id=missing.id).count(), 0)

    def test_refresh_missing_don_t_remove_manually_ignored(self):
        missing = MissingSubject.objects.create()
        missing.ignore = True
        missing.save()
        prepare_test_redcap_connection()

        self.assertEqual(MissingSubject.objects.filter(id=missing.id).count(), 1)

        redcap_connection = RedcapConnector()
        redcap_connection.refresh_missing()
        self.assertTrue(MissingSubject.objects.count() > 0)
        self.assertEqual(MissingSubject.objects.filter(id=missing.id).count(), 1)

    def test_refresh_inconsistent_data(self):
        prepare_test_redcap_connection()
        subject = create_study_subject()
        # noinspection SpellCheckingInspection
        subject.nd_number = 'NDtest_external'
        subject.save()

        redcap_connection = RedcapConnector()
        redcap_connection.refresh_inconsistent()
        self.assertTrue(InconsistentSubject.objects.count() > 0)

    def test_different_string(self):
        self.assertFalse(different_string(None, None))
        self.assertFalse(different_string(None, ""))
        self.assertFalse(different_string("", None))
        self.assertFalse(different_string(" abc", "abc "))
        self.assertTrue(different_string("y", "x"))