class BestMatchSentimentComparisonTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using the similarity of sentiment polarity as a comparison function.
    """

    def setUp(self):
        super().setUp()
        from chatterbot.trainers import ListTrainer
        from chatterbot.comparisons import sentiment_comparison

        self.trainer = ListTrainer(
            self.chatbot,
            show_training_progress=False
        )

        self.adapter = BestMatch(
            self.chatbot,
            statement_comparison_function=sentiment_comparison
        )
        self.adapter.initialize()

    def test_exact_input(self):
        self.trainer.train([
            'What is your favorite flavor of ice cream?',
            'I enjoy raspberry ice cream.',
            'I am glad to hear that.',
            'Thank you.'
        ])

        happy_statement = Statement(text='I enjoy raspberry ice cream.')
        response = self.adapter.process(happy_statement)

        self.assertEqual(response.confidence, 1)
        self.assertEqual(response.text, 'I am glad to hear that.')

    def test_close_input(self):

        self.trainer.train([
            'What is your favorite flavor of ice cream?',
            'I enjoy raspberry ice cream.',
            'I am glad to hear that.',
            'Thank you.'
        ])

        happy_statement = Statement(text='I enjoy raspberry.')
        response = self.adapter.process(happy_statement)

        self.assertEqual(response.text, 'I am glad to hear that.')
        self.assertAlmostEqual(response.confidence, 0.75, places=1)
Exemple #2
0
class BestMatchSentimentComparisonTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using the similarity of sentiment polarity as a comparison function.
    """

    def setUp(self):
        super(BestMatchSentimentComparisonTestCase, self).setUp()
        from chatterbot.trainers import ListTrainer
        from chatterbot.comparisons import sentiment_comparison

        self.trainer = ListTrainer(
            self.chatbot,
            show_training_progress=False
        )

        self.adapter = BestMatch(
            statement_comparison_function=sentiment_comparison
        )
        self.adapter.set_chatbot(self.chatbot)
        self.adapter.initialize()

    def test_exact_input(self):
        self.trainer.train([
            'What is your favorite flavor of ice cream?',
            'I enjoy raspberry ice cream.',
            'I am glad to hear that.',
            'Thank you.'
        ])

        happy_statement = Statement('I enjoy raspberry ice cream.')
        response = self.adapter.process(happy_statement)

        self.assertEqual(response.confidence, 1)
        self.assertEqual(response.text, 'I am glad to hear that.')

    def test_close_input(self):

        self.trainer.train([
            'What is your favorite flavor of ice cream?',
            'I enjoy raspberry ice cream.',
            'I am glad to hear that.',
            'Thank you.'
        ])

        happy_statement = Statement('I enjoy raspberry.')
        response = self.adapter.process(happy_statement)

        self.assertEqual(response.text, 'I am glad to hear that.')
        self.assertAlmostEqual(response.confidence, 0.75, places=1)
class BestMatchTestCase(ChatBotTestCase):
    """
    Unit tests for the BestMatch logic adapter.
    """
    def setUp(self):
        super().setUp()
        self.adapter = BestMatch(self.chatbot)

    def test_no_choices(self):
        """
        An exception should be raised if there is no data in the database.
        """
        statement = Statement(text='What is your quest?')
        response = self.adapter.get(statement)

        self.assertEqual(response.text, 'What is your quest?')
        self.assertEqual(response.confidence, 0)

    def test_excluded_words(self):
        """
        Test that the logic adapter cannot return a response containing
        any of the listed words for exclusion.
        """
        self.chatbot.storage.create(text='I like to count.')
        self.chatbot.storage.create(text='Counting is dumb.',
                                    in_response_to='I like to count.')
        self.chatbot.storage.create(text='Counting is fun!',
                                    in_response_to='I like to count.')

        self.adapter.excluded_words = ['dumb']

        response = self.adapter.process(Statement(text='I like to count.'))

        self.assertEqual(response.confidence, 1)
        self.assertEqual(response.text, 'Counting is fun!')
class BestMatchSynsetDistanceTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using the synset_distance comparison function.
    """

    def setUp(self):
        super().setUp()
        from chatterbot.comparisons import synset_distance

        self.adapter = BestMatch(
            self.chatbot,
            statement_comparison_function=synset_distance
        )

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        self.chatbot.storage.create_many([
            Statement(text='This is a lovely bog.', in_response_to='This is a lovely bog.'),
            Statement(text='This is a beautiful swamp.', in_response_to='This is a beautiful swamp.'),
            Statement(text='It smells like a swamp.', in_response_to='It smells like a swamp.')
        ])

        statement = Statement(text='This is a lovely swamp.')
        match = self.adapter.get(statement)

        self.assertEqual('This is a lovely bog.', match)

    def test_different_punctuation(self):
        self.adapter.chatbot.storage.create_many([
            Statement(text='Who are you?'),
            Statement(text='Are you good?'),
            Statement(text='You are good')
        ])

        statement = Statement(text='Are you good')
        match = self.adapter.get(statement)

        self.assertEqual('Are you good?', match)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.count = MagicMock(return_value=1)
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement(text='Random')
        )

        match = self.adapter.process(Statement(text='Blah'))

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')
class BestMatchSynsetDistanceTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using the synset_distance comparison function.
    """
    def setUp(self):
        super().setUp()
        from chatterbot.comparisons import synset_distance

        self.adapter = BestMatch(self.chatbot,
                                 statement_comparison_function=synset_distance)

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        self.chatbot.storage.create_many([
            Statement(text='This is a lovely bog.',
                      in_response_to='This is a lovely bog.'),
            Statement(text='This is a beautiful swamp.',
                      in_response_to='This is a beautiful swamp.'),
            Statement(text='It smells like a swamp.',
                      in_response_to='It smells like a swamp.')
        ])

        statement = Statement(text='This is a lovely swamp.')
        match = self.adapter.get(statement)

        self.assertEqual('This is a lovely bog.', match)

    def test_different_punctuation(self):
        self.adapter.chatbot.storage.create_many([
            Statement(text='Who are you?'),
            Statement(text='Are you good?'),
            Statement(text='You are good')
        ])

        statement = Statement(text='Are you good')
        match = self.adapter.get(statement)

        self.assertEqual('Are you good?', match)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.count = MagicMock(return_value=1)
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement(text='Random'))

        match = self.adapter.process(Statement(text='Blah'))

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')
    def process(self,
                input_statement,
                additional_response_selection_parameters=None):
        text = input_statement.text
        statement = Statement(text="")
        statement.confidence = 1
        if 'change' in text and 'edition' in text:
            last_word = str(text).split(" ")[-1]
            if last_word in self.editions:
                self.edition = last_word  # if the given edition is wrong, it will always default
                statement.text = f'Your new edition is {self.edition}'
                return statement
            else:
                statement.text = f'Try choosing an edition from {self.editions}'
                return statement

        if 'cyclic' in text:
            for category in self.categories.keys():
                if category in text:
                    self.news_task.active_category = category
                    self.news_thread = Process(target=self.news_task.news_bot)
                    self.news_thread.start()
                    statement.text = f'Cyclic {category} news feed turned on'
                    return statement

        if self.news_thread and 'turn off' in text:
            self.news_thread.terminate()
            statement.text = f'Cyclic news feed turned off'
            return statement

        if 'search' in text:
            regex = re.compile('search(?:\sfor)?\s([\w\s]+)$', re.IGNORECASE)
            search_terms = regex.search(text).group(1)
            title, link = self.find_article_keyword(search_terms)
            statement.text = f'Here is an article about {search_terms}. Title: {title}. Link: {link}'
            return statement

        title = None
        link = None

        statement = BestMatch.process(self, input_statement=input_statement)
        for category, val in self.categories.items():
            if val in statement.text:
                title, link = self.news_task.get_article(category)

        if link is not None:
            statement.text += f' Title: {title}. Link: {link}'

        return statement
Exemple #7
0
    def test_best_match(self):
        from chatterbot.logic import BestMatch

        adapter = BestMatch(self.chatbot)

        statement1 = self.chatbot.storage.create(
            text='Do you like programming?', conversation='test')

        self.chatbot.storage.create(text='Yes',
                                    in_response_to=statement1.text,
                                    conversation='test')

        response = adapter.process(statement1)

        self.assertEqual(response.text, 'Yes')
        self.assertEqual(response.confidence, 1)
    def test_best_match(self):
        from chatterbot.logic import BestMatch

        adapter = BestMatch()
        adapter.set_chatbot(self.chatbot)

        statement1 = Statement(text='Do you like programming?')
        statement1.save()

        statement2 = Statement(text='Yes')
        statement2.save()

        response = Response(statement=statement1, response=statement2)
        response.save()

        response = adapter.process(statement1)

        self.assertEqual(response.text, 'Yes')
        self.assertEqual(response.confidence, 1)
    def test_best_match(self):
        from chatterbot.logic import BestMatch

        adapter = BestMatch()
        adapter.set_chatbot(self.chatbot)

        statement1 = Statement(text='Do you like programming?')
        statement1.save()

        statement2 = Statement(text='Yes')
        statement2.save()

        response = Response(statement=statement1, response=statement2)
        response.save()

        response = adapter.process(statement1)

        self.assertEqual(response.text, 'Yes')
        self.assertEqual(response.confidence, 1)
class BestMatchTestCase(ChatBotTestCase):
    """
    Unit tests for the BestMatch logic adapter.
    """

    def setUp(self):
        super().setUp()
        self.adapter = BestMatch(self.chatbot)

    def test_no_choices(self):
        """
        An exception should be raised if there is no data in the database.
        """
        statement = Statement(text='What is your quest?')
        response = self.adapter.get(statement)

        self.assertEqual(response.text, 'What is your quest?')
        self.assertEqual(response.confidence, 0)

    def test_excluded_words(self):
        """
        Test that the logic adapter cannot return a response containing
        any of the listed words for exclusion.
        """
        self.chatbot.storage.create(
            text='I like to count.'
        )
        self.chatbot.storage.create(
            text='Counting is dumb.',
            in_response_to='I like to count.'
        )
        self.chatbot.storage.create(
            text='Counting is fun!',
            in_response_to='I like to count.'
        )

        self.adapter.excluded_words = ['dumb']

        response = self.adapter.process(Statement(text='I like to count.'))

        self.assertEqual(response.confidence, 1)
        self.assertEqual(response.text, 'Counting is fun!')
    def test_best_match(self):
        from chatterbot.logic import BestMatch

        adapter = BestMatch(self.chatbot)

        statement1 = self.chatbot.storage.create(
            text='Do you like programming?',
            conversation='test'
        )

        self.chatbot.storage.create(
            text='Yes',
            in_response_to=statement1.text,
            conversation='test'
        )

        response = adapter.process(statement1)

        self.assertEqual(response.text, 'Yes')
        self.assertEqual(response.confidence, 1)
class BestMatchSynsetDistanceTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using the synset_distance comparison function.
    """
    def setUp(self):
        super(BestMatchSynsetDistanceTestCase, self).setUp()
        from chatterbot.utils import nltk_download_corpus
        from chatterbot.comparisons import synset_distance

        nltk_download_corpus('stopwords')
        nltk_download_corpus('wordnet')
        nltk_download_corpus('punkt')

        self.adapter = BestMatch(statement_comparison_function=synset_distance)

        # Add a mock storage adapter to the logic adapter
        self.adapter.set_chatbot(self.chatbot)

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        possible_choices = [
            Statement('This is a lovely bog.',
                      in_response_to=[Response('This is a lovely bog.')]),
            Statement('This is a beautiful swamp.',
                      in_response_to=[Response('This is a beautiful swamp.')]),
            Statement('It smells like a swamp.',
                      in_response_to=[Response('It smells like a swamp.')])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(
            return_value=possible_choices)

        statement = Statement('This is a lovely swamp.')
        match = self.adapter.get(statement)

        self.assertEqual('This is a lovely bog.', match)

    def test_different_punctuation(self):
        possible_choices = [
            Statement('Who are you?'),
            Statement('Are you good?'),
            Statement('You are good')
        ]
        self.adapter.chatbot.storage.get_response_statements = MagicMock(
            return_value=possible_choices)

        statement = Statement('Are you good')
        match = self.adapter.get(statement)

        self.assertEqual('Are you good?', match)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.count = MagicMock(return_value=1)
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement('Random'))

        confidence, match = self.adapter.process(Statement('Blah'))

        self.assertEqual(confidence, 0)
        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')
class BestMatchSynsetDistanceTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using the synset_distance comparison function.
    """

    def setUp(self):
        super(BestMatchSynsetDistanceTestCase, self).setUp()
        from chatterbot.utils import nltk_download_corpus
        from chatterbot.comparisons import synset_distance

        nltk_download_corpus('stopwords')
        nltk_download_corpus('wordnet')
        nltk_download_corpus('punkt')

        self.adapter = BestMatch(
            statement_comparison_function=synset_distance
        )

        # Add a mock storage adapter to the logic adapter
        self.adapter.set_chatbot(self.chatbot)

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        possible_choices = [
            Statement('This is a lovely bog.', in_response_to=[Response('This is a lovely bog.')]),
            Statement('This is a beautiful swamp.', in_response_to=[Response('This is a beautiful swamp.')]),
            Statement('It smells like a swamp.', in_response_to=[Response('It smells like a swamp.')])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(
            return_value=possible_choices
        )

        statement = Statement('This is a lovely swamp.')
        match = self.adapter.get(statement)

        self.assertEqual('This is a lovely bog.', match)

    def test_different_punctuation(self):
        possible_choices = [
            Statement('Who are you?'),
            Statement('Are you good?'),
            Statement('You are good')
        ]
        self.adapter.chatbot.storage.get_response_statements = MagicMock(
            return_value=possible_choices
        )

        statement = Statement('Are you good')
        match = self.adapter.get(statement)

        self.assertEqual('Are you good?', match)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.count = MagicMock(return_value=1)
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement('Random')
        )

        confidence, match = self.adapter.process(Statement('Blah'))

        self.assertEqual(confidence, 0)
        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')
Exemple #14
0
class BestMatchTestCase(ChatBotTestCase):
    """
    Unit tests for the BestMatch logic adapter.
    """
    def setUp(self):
        super().setUp()
        self.adapter = BestMatch(self.chatbot)

    def test_no_data(self):
        """
        If there is no data to return, an exception should be raised.
        """
        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'What is your quest?')
        self.assertEqual(response.confidence, 0)

    def test_no_choices(self):
        """
        The input should be returned as the closest match if there
        are no other results to return.
        """
        self.chatbot.storage.create(text='Random')

        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'Random')
        self.assertEqual(response.confidence, 0)

    def test_no_known_responses(self):
        """
        A match can be selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        from unittest.mock import MagicMock

        self.chatbot.storage.update = MagicMock()
        self.chatbot.storage.count = MagicMock(return_value=1)
        self.chatbot.storage.get_random = MagicMock(return_value=Statement(
            text='Random'))

        match = self.adapter.process(Statement(text='Blah'))

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')

    def test_match_with_no_response(self):
        """
        A response to the input should be returned if a response is known.
        """
        self.chatbot.storage.create(text='To eat pasta.',
                                    in_response_to='What is your quest?')

        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'To eat pasta.')
        self.assertEqual(response.confidence, 0)

    def test_match_with_response(self):
        """
        The response to the input should be returned if a response is known.
        """
        self.chatbot.storage.create(text='To eat pasta.',
                                    in_response_to='What is your quest?')
        self.chatbot.storage.create(text='What is your quest?')

        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'To eat pasta.')
        self.assertEqual(response.confidence, 1)

    def test_excluded_words(self):
        """
        Test that the logic adapter cannot return a response containing
        any of the listed words for exclusion.
        """
        self.chatbot.storage.create(text='I like to count.')
        self.chatbot.storage.create(text='Counting is dumb.',
                                    in_response_to='I like to count.')
        self.chatbot.storage.create(text='Counting is fun!',
                                    in_response_to='I like to count.')

        self.adapter.excluded_words = ['dumb']

        response = self.adapter.process(Statement(text='I like to count.'))

        self.assertEqual(response.confidence, 1)
        self.assertEqual(response.text, 'Counting is fun!')

    def test_low_confidence(self):
        """
        Test the case that a high confidence response is not known.
        """
        statement = Statement(text='Is this a tomato?')
        match = self.adapter.process(statement)

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, statement.text)

    def test_low_confidence_options_list(self):
        """
        Test the case that a high confidence response is not known.
        """
        self.adapter.default_responses = [Statement(text='No')]

        statement = Statement(text='Is this a tomato?')
        match = self.adapter.process(statement)

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'No')

    def test_text_search_algorithm(self):
        """
        Test that a close match is found when the text_search algorithm is used.
        """
        self.adapter = BestMatch(self.chatbot,
                                 search_algorithm_name='text_search')

        self.chatbot.storage.create(text='I am hungry.')
        self.chatbot.storage.create(text='Okay, what would you like to eat?',
                                    in_response_to='I am hungry.')
        self.chatbot.storage.create(text='Can you help me?')
        self.chatbot.storage.create(text='Sure, what seems to be the problem?',
                                    in_response_to='Can you help me?')

        statement = Statement(text='Could you help me?')
        match = self.adapter.process(statement)

        self.assertEqual(match.confidence, 0.82)
        self.assertEqual(match.text, 'Sure, what seems to be the problem?')
Exemple #15
0
class BestMatchLevenshteinDistanceTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using Levenshtein distance as a comparison function.
    """
    def setUp(self):
        super().setUp()
        from chatterbot.comparisons import levenshtein_distance

        self.adapter = BestMatch(
            self.chatbot, statement_comparison_function=levenshtein_distance)

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        self.chatbot.storage.create_many([
            Statement(text='Who do you love?',
                      in_response_to='I hear you are going on a quest?'),
            Statement(text='What is the meaning of life?',
                      in_response_to='Yuck, black licorice jelly beans.'),
            Statement(text='I am Iron Man.',
                      in_response_to='What... is your quest?'),
            Statement(text='What... is your quest?',
                      in_response_to='I am Iron Man.'),
            Statement(text='Yuck, black licorice jelly beans.',
                      in_response_to='What is the meaning of life?'),
            Statement(text='I hear you are going on a quest?',
                      in_response_to='Who do you love?'),
        ])

        statement = Statement(text='What is your quest?')

        match = self.adapter.get(statement)

        self.assertEqual('What... is your quest?', match)

    def test_confidence_exact_match(self):
        self.chatbot.storage.create(text='What is your quest?',
                                    in_response_to='What is your quest?')

        statement = Statement(text='What is your quest?')
        match = self.adapter.get(statement)

        self.assertEqual(match.confidence, 1)

    def test_confidence_half_match(self):
        self.chatbot.storage.create(text='xxyy', in_response_to='xxyy')

        statement = Statement(text='wwxx')
        match = self.adapter.get(statement)

        self.assertEqual(match.confidence, 0.5)

    def test_confidence_no_match(self):
        self.chatbot.storage.create(text='xxx', in_response_to='xxx')

        statement = Statement(text='yyy')
        match = self.adapter.get(statement)

        self.assertEqual(match.confidence, 0)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.count = MagicMock(return_value=1)
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement(text='Random'))

        match = self.adapter.process(Statement(text='Blah'))

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')
class BestMatchLevenshteinDistanceTestCase(TestCase):
    """
    Integration tests for the BestMatch logic adapter
    using Levenshtein distance as a comparison function.
    """
    def setUp(self):
        from chatterbot.comparisons import levenshtein_distance

        self.adapter = BestMatch(
            statement_comparison_function=levenshtein_distance)

        # Add a mock chatbot to the logic adapter
        self.adapter.set_chatbot(MockChatBot())

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        possible_choices = [
            Statement(
                "Who do you love?",
                in_response_to=[Response("I hear you are going on a quest?")]),
            Statement("What is the meaning of life?",
                      in_response_to=[
                          Response("Yuck, black licorice jelly beans.")
                      ]),
            Statement("I am Iron Man.",
                      in_response_to=[Response("What... is your quest?")]),
            Statement("What... is your quest?",
                      in_response_to=[Response("I am Iron Man.")]),
            Statement(
                "Yuck, black licorice jelly beans.",
                in_response_to=[Response("What is the meaning of life?")]),
            Statement("I hear you are going on a quest?",
                      in_response_to=[Response("Who do you love?")]),
        ]
        self.adapter.chatbot.storage.filter = MagicMock(
            return_value=possible_choices)

        statement = Statement("What is your quest?")

        confidence, match = self.adapter.get(statement)

        self.assertEqual("What... is your quest?", match)

    def test_confidence_exact_match(self):
        possible_choices = [
            Statement("What is your quest?",
                      in_response_to=[Response("What is your quest?")])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(
            return_value=possible_choices)

        statement = Statement("What is your quest?")
        confidence, match = self.adapter.get(statement)

        self.assertEqual(confidence, 1)

    def test_confidence_half_match(self):
        possible_choices = [
            Statement("xxyy", in_response_to=[Response("xxyy")])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(
            return_value=possible_choices)

        statement = Statement("wwxx")
        confidence, match = self.adapter.get(statement)

        self.assertEqual(confidence, 0.5)

    def test_confidence_no_match(self):
        possible_choices = [Statement("xxx", in_response_to=[Response("xxx")])]
        self.adapter.chatbot.storage.filter = MagicMock(
            return_value=possible_choices)

        statement = Statement("yyy")
        confidence, match = self.adapter.get(statement)

        self.assertEqual(confidence, 0)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.filter = MagicMock(return_value=[])
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement("Random"))

        confidence, match = self.adapter.process(Statement("Blah"))

        self.assertEqual(confidence, 0)
        self.assertEqual(match.text, "Random")
class BestMatchTestCase(ChatBotTestCase):
    """
    Unit tests for the BestMatch logic adapter.
    """

    def setUp(self):
        super().setUp()
        self.adapter = BestMatch(self.chatbot)

    def test_no_data(self):
        """
        If there is no data to return, an exception should be raised.
        """
        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'What is your quest?')
        self.assertEqual(response.confidence, 0)

    def test_no_choices(self):
        """
        The input should be returned as the closest match if there
        are no other results to return.
        """
        self.chatbot.storage.create(text='Random')

        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'Random')
        self.assertEqual(response.confidence, 0)

    def test_no_known_responses(self):
        """
        A match can be selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        from unittest.mock import MagicMock

        self.chatbot.storage.update = MagicMock()
        self.chatbot.storage.count = MagicMock(return_value=1)
        self.chatbot.storage.get_random = MagicMock(
            return_value=Statement(text='Random')
        )

        match = self.adapter.process(Statement(text='Blah'))

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'Random')

    def test_match_with_no_response(self):
        """
        A response to the input should be returned if a response is known.
        """
        self.chatbot.storage.create(
            text='To eat pasta.',
            in_response_to='What is your quest?'
        )

        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'To eat pasta.')
        self.assertEqual(response.confidence, 0)

    def test_match_with_response(self):
        """
        The response to the input should be returned if a response is known.
        """
        self.chatbot.storage.create(
            text='To eat pasta.',
            in_response_to='What is your quest?'
        )
        self.chatbot.storage.create(
            text='What is your quest?'
        )

        statement = Statement(text='What is your quest?')
        response = self.adapter.process(statement)

        self.assertEqual(response.text, 'To eat pasta.')
        self.assertEqual(response.confidence, 1)

    def test_excluded_words(self):
        """
        Test that the logic adapter cannot return a response containing
        any of the listed words for exclusion.
        """
        self.chatbot.storage.create(
            text='I like to count.'
        )
        self.chatbot.storage.create(
            text='Counting is dumb.',
            in_response_to='I like to count.'
        )
        self.chatbot.storage.create(
            text='Counting is fun!',
            in_response_to='I like to count.'
        )

        self.adapter.excluded_words = ['dumb']

        response = self.adapter.process(Statement(text='I like to count.'))

        self.assertEqual(response.confidence, 1)
        self.assertEqual(response.text, 'Counting is fun!')

    def test_low_confidence(self):
        """
        Test the case that a high confidence response is not known.
        """
        statement = Statement(text='Is this a tomato?')
        match = self.adapter.process(statement)

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, statement.text)

    def test_low_confidence_options_list(self):
        """
        Test the case that a high confidence response is not known.
        """
        self.adapter.default_responses = [
            Statement(text='No')
        ]

        statement = Statement(text='Is this a tomato?')
        match = self.adapter.process(statement)

        self.assertEqual(match.confidence, 0)
        self.assertEqual(match.text, 'No')
class BestMatchLevenshteinDistanceTestCase(ChatBotTestCase):
    """
    Integration tests for the BestMatch logic adapter
    using Levenshtein distance as a comparison function.
    """

    def setUp(self):
        super(BestMatchLevenshteinDistanceTestCase, self).setUp()
        from chatterbot.comparisons import levenshtein_distance

        self.adapter = BestMatch(
            statement_comparison_function=levenshtein_distance
        )
        self.adapter.set_chatbot(self.chatbot)

    def test_get_closest_statement(self):
        """
        Note, the content of the in_response_to field for each of the
        test statements is only required because the logic adapter will
        filter out any statements that are not in response to a known statement.
        """
        possible_choices = [
            Statement("Who do you love?", in_response_to=[Response("I hear you are going on a quest?")]),
            Statement("What is the meaning of life?", in_response_to=[Response("Yuck, black licorice jelly beans.")]),
            Statement("I am Iron Man.", in_response_to=[Response("What... is your quest?")]),
            Statement("What... is your quest?", in_response_to=[Response("I am Iron Man.")]),
            Statement("Yuck, black licorice jelly beans.", in_response_to=[Response("What is the meaning of life?")]),
            Statement("I hear you are going on a quest?", in_response_to=[Response("Who do you love?")]),
        ]
        self.adapter.chatbot.storage.filter = MagicMock(return_value=possible_choices)

        statement = Statement("What is your quest?")

        confidence, match = self.adapter.get(statement)

        self.assertEqual("What... is your quest?", match)

    def test_confidence_exact_match(self):
        possible_choices = [
            Statement("What is your quest?", in_response_to=[Response("What is your quest?")])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(return_value=possible_choices)

        statement = Statement("What is your quest?")
        confidence, match = self.adapter.get(statement)

        self.assertEqual(confidence, 1)

    def test_confidence_half_match(self):
        possible_choices = [
            Statement("xxyy", in_response_to=[Response("xxyy")])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(return_value=possible_choices)

        statement = Statement("wwxx")
        confidence, match = self.adapter.get(statement)

        self.assertEqual(confidence, 0.5)

    def test_confidence_no_match(self):
        possible_choices = [
            Statement("xxx", in_response_to=[Response("xxx")])
        ]
        self.adapter.chatbot.storage.filter = MagicMock(return_value=possible_choices)

        statement = Statement("yyy")
        confidence, match = self.adapter.get(statement)

        self.assertEqual(confidence, 0)

    def test_no_known_responses(self):
        """
        In the case that a match is selected which has no known responses.
        In this case a random response will be returned, but the confidence
        should be zero because it is a random choice.
        """
        self.adapter.chatbot.storage.update = MagicMock()
        self.adapter.chatbot.storage.count = MagicMock(return_value=1)
        self.adapter.chatbot.storage.get_random = MagicMock(
            return_value=Statement("Random")
        )

        confidence, match = self.adapter.process(Statement("Blah"))

        self.assertEqual(confidence, 0)
        self.assertEqual(match.text, "Random")