Exemplo n.º 1
0
    def test_format_message_with_bot(self):
        config = BotConfiguration()
        config._section_name = "testbot"
        bot = Bot(config)

        msg = YLogger.format_message(bot, "Test Message")
        self.assertIsNotNone(msg)
        self.assertEquals("[] [testbot] - Test Message", msg)
Exemplo n.º 2
0
    def test_with_data(self):
        yaml = YamlConfigurationFile()
        self.assertIsNotNone(yaml)
        yaml.load_from_text("""
        bot:
            prompt: ">>>"
            initial_question: Hi, how can I help you today?
            initial_question_srai: YINITIALQUESTION
            default_response: Sorry, I don't have an answer for that!
            default_response_srai: YDEFAULTRESPONSE
            empty_string: YEMPTY
            exit_response: So long, and thanks for the fish!
            exit_response_srai: YEXITRESPONSE
            override_properties: true
            max_question_recursion: 1000
            max_question_timeout: 60
            max_search_depth: 100
            max_search_timeout: 60
            
            spelling:
              classname: programr.spelling.norvig.NorvigSpellingChecker
              alphabet: 'abcdefghijklmnopqrstuvwxyz'
              corpus: $BOT_ROOT/corpus.txt
              check_before: true
              check_and_retry: true
              
            conversations:
              type: file
              config_name: file_storage
        
            file_storage:
              dir: $BOT_ROOT/conversations

        """, ConsoleConfiguration(), ".")

        bot_config = BotConfiguration()
        bot_config.load_configuration(yaml, ".")

        self.assertEqual("Hi, how can I help you today?", bot_config.initial_question)
        self.assertEqual("YINITIALQUESTION", bot_config.initial_question_srai)
        self.assertEqual("Sorry, I don't have an answer for that!", bot_config.default_response)
        self.assertEqual("YDEFAULTRESPONSE", bot_config.default_response_srai)
        self.assertEqual("So long, and thanks for the fish!", bot_config.exit_response)
        self.assertEqual("YEXITRESPONSE", bot_config.exit_response_srai)
        self.assertEqual("YEMPTY", bot_config.empty_string)
        self.assertEqual(bot_config.max_question_recursion, 1000)
        self.assertEqual(bot_config.max_question_timeout, 60)
        self.assertEqual(bot_config.max_search_depth, 100)
        self.assertEqual(bot_config.max_search_timeout, 60)
        self.assertTrue(bot_config.override_properties)

        self.assertIsNotNone(bot_config.spelling)
        self.assertEqual("programr.spelling.norvig.NorvigSpellingChecker", bot_config.spelling.classname)

        self.assertIsNotNone(bot_config.conversations)
        self.assertEquals(bot_config.conversations.type, "file")
        self.assertIsNotNone(bot_config.conversations.storage)
        self.assertEquals(bot_config.conversations.storage.dir, "./conversations")
Exemplo n.º 3
0
    def test_learn_multi_user(self):
        client_context1 = ClientContext(TestClient(), "testid")
        client_context1.bot = Bot(BotConfiguration())
        client_context1.brain = client_context1.bot.brain

        template = ET.fromstring("""
			<template>
				<learn>
				    <category>
				        <pattern>HELLO THERE ONE</pattern>
				        <template>HIYA ONE</template>
				    </category>
				</learn>
			</template>
			""")

        ast = self._graph.parse_template_expression(template)

        learn_node = ast.children[0]

        learn_node.resolve(client_context1)

        response = client_context1.bot.ask_question(client_context1, "HELLO THERE ONE")
        self.assertEqual("HIYA ONE", response)

        client_context2 = ClientContext(TestClient(), "testid")
        client_context2.bot = Bot(BotConfiguration())
        client_context2.brain = client_context2.bot.brain

        template = ET.fromstring("""
			<template>
				<learn>
				    <category>
				        <pattern>HELLO THERE TWO</pattern>
				        <template>HIYA TWO</template>
				    </category>
				</learn>
			</template>
			""")

        ast = self._graph.parse_template_expression(template)

        learn_node = ast.children[0]

        learn_node.resolve(client_context2)

        response = client_context2.bot.ask_question(client_context2, "HELLO THERE TWO")
        self.assertEqual("HIYA TWO", response)

        # Now try and ask each others questions

        response = client_context1.bot.ask_question(client_context1, "HELLO THERE TWO")
        self.assertEqual("", response)

        response = client_context2.bot.ask_question(client_context2, "HELLO THERE ONE")
        self.assertEqual("", response)
Exemplo n.º 4
0
    def test_get_exit_response_exit_response_only(self):

        bot_config = BotConfiguration()
        self.assertIsNotNone(bot_config)

        bot_config.exit_response = "Default response!"

        bot = Bot(bot_config)
        self.assertIsNotNone(bot)

        self.assertEquals("Default response!", bot.get_exit_response(self._client_context))
Exemplo n.º 5
0
    def test_get_initial_question_initial_question_only(self):

        bot_config = BotConfiguration()
        self.assertIsNotNone(bot_config)

        bot_config.initial_question = "Default response!"

        bot = Bot(bot_config)
        self.assertIsNotNone(bot)

        self.assertEquals("Default response!", bot.get_initial_question(self._client_context))
Exemplo n.º 6
0
    def test_get_exit_response_exit_response_srai_no_match(self):

        bot_config = BotConfiguration()
        self.assertIsNotNone(bot_config)

        bot_config.exit_response_srai = "YDEFAULTRESPONSE"
        bot_config.exit_response = "Default response!"

        bot = Bot(bot_config)
        self.assertIsNotNone(bot)

        self.assertEquals("Default response!", bot.get_exit_response(self._client_context))
Exemplo n.º 7
0
    def test_empty_config_init(self):
        configuration = BotConfiguration()
        configuration._bot_selector = "programr.clients.client.DefaultBrainSelector"

        bot = Bot(configuration)

        factory = BrainFactory(bot)
        self.assertIsNotNone(factory)

        brain = factory.select_brain()
        self.assertIsNotNone(brain)
        self.assertIsInstance(brain, Brain)
Exemplo n.º 8
0
    def test_format_message_with_client_and_bot_and_brain(self):
        client = TestClient()

        bot_config = BotConfiguration()
        bot_config._section_name = "testbot"
        bot = Bot(bot_config, client)

        brain_config = BrainConfiguration()
        brain_config._section_name = "testbrain"
        brain = Brain(bot, brain_config)

        msg = YLogger.format_message(brain, "Test Message")
        self.assertIsNotNone(msg)
        self.assertEquals("[testclient] [testbot] [testbrain] - Test Message",
                          msg)
Exemplo n.º 9
0
    def test_bot_chat_loop(self):

        bot = Bot(BotConfiguration())
        self.assertIsNotNone(bot)
        self.assertIsInstance(bot, Bot)
        bot.configuration._default_response = "Sorry, I don't have an answer for that right now"

        response = bot.ask_question(self._client_context, "hello")
        self.assertIsNotNone(response)
        self.assertEqual(response, "Sorry, I don't have an answer for that right now")

        response = bot.ask_question(self._client_context, "hello again")
        self.assertIsNotNone(response)
        self.assertEqual(response, "Sorry, I don't have an answer for that right now")

        response = bot.ask_question(self._client_context, "goodbye")
        self.assertIsNotNone(response)
        self.assertEqual(response, "Sorry, I don't have an answer for that right now")

        conversation = bot.get_conversation(self._client_context)
        self.assertIsNotNone(conversation)

        self.assertEqual(conversation.previous_nth_question(2).sentence(0).text(), "hello")
        self.assertEqual(conversation.previous_nth_question(2).sentence(0).response, "Sorry, I don't have an answer for that right now")

        self.assertEqual(conversation.previous_nth_question(1).sentence(0).text(), "hello again")
        self.assertEqual(conversation.previous_nth_question(1).sentence(0).response, "Sorry, I don't have an answer for that right now")

        self.assertEqual(conversation.previous_nth_question(0).sentence(0).text(), "goodbye")
        self.assertEqual(conversation.previous_nth_question(0).sentence(0).response, "Sorry, I don't have an answer for that right now")
Exemplo n.º 10
0
    def test_persistence(self):
        client = TestClient()
        client_context = client.create_client_context("testid")
        bot_config = BotConfiguration()
        bot_config.conversations._type = "file"
        bot_config.conversations._storage = BotConversationsFileStorageConfiguration("test")
        bot_config.conversations._storage._dir = os.path.dirname(__file__)
        bot_config.conversations._max_histories = 3
        client_context.bot = Bot(bot_config)

        filename = bot_config.conversations._storage._dir + os.sep + client_context.userid + ".convo"
        if os.path.exists(filename):
            os.remove(filename)
        self.assertFalse(os.path.exists(filename))

        conversation = client_context.bot.get_conversation(client_context)
        conversation.properties['name'] = "fred"

        client_context.bot.save_conversation(client_context.userid)
        self.assertTrue(os.path.exists(filename))

        test_bot2 = Bot(bot_config)
        conversation2 = test_bot2.get_conversation(client_context)
        self.assertIsNotNone(conversation2.property('name'))
        self.assertEqual('fred', conversation2.property('name'))

        self.assertTrue(os.path.exists(filename))
        if os.path.exists(filename):
           os.remove(filename)
        self.assertFalse(os.path.exists(filename))
Exemplo n.º 11
0
    def setUp(self):

        self._client_context = ClientContext(TestClient(), "testid")
        self._client_context.bot = Bot(BotConfiguration())
        self._client_context.brain = self._client_context.bot.brain

        self._graph = self._client_context.bot.brain.aiml_parser.template_parser

        self.test_sentence = Sentence(self._client_context.brain.nlp.tokenizer,
                                      "test sentence")

        test_node = PatternOneOrMoreWildCardNode("*")

        self.test_sentence._matched_context = MatchContext(
            max_search_depth=100,
            max_search_timeout=-1,
            tokenizer=self._client_context.brain.nlp.tokenizer)
        self.test_sentence._matched_context._matched_nodes = [
            Match(Match.WORD, test_node, 'one'),
            Match(Match.WORD, test_node, 'two'),
            Match(Match.WORD, test_node, 'three'),
            Match(Match.WORD, test_node, 'four'),
            Match(Match.WORD, test_node, 'five'),
            Match(Match.WORD, test_node, 'six'),
            Match(Match.TOPIC, test_node, '*'),
            Match(Match.THAT, test_node, '*')
        ]

        conversation = self._client_context.bot.get_conversation(
            self._client_context)
        question = Question.create_from_sentence(self.test_sentence)
        conversation._questions.append(question)
Exemplo n.º 12
0
    def test_get_exit_response_exit_response_srai_match(self):

        bot_config = BotConfiguration()
        self.assertIsNotNone(bot_config)
        bot_config.exit_response_srai = "YDEFAULTRESPONSE"
        bot_config.exit_response = "Default response!"

        bot = MockBot(bot_config)
        self.assertIsNotNone(bot)

        client_context2 = ClientContext(TestClient(), "testid2")
        client_context2._bot = bot
        client_context2._brain = MockBrain(bot, bot.configuration.brain_config[0])
        client_context2._brain._response = "Y DEFAULT RESPONSE"

        self.assertEquals("Y DEFAULT RESPONSE", bot.get_exit_response(client_context2))
Exemplo n.º 13
0
 def __init__(self, name):
     super().__init__(name)
     self._bot_configs = []
     self._bot_configs.append(BotConfiguration("bot"))
     self._license_keys = None
     self._bot_selector = None
     self._scheduler = SchedulerConfiguration()
     self._renderer = None
Exemplo n.º 14
0
    def test_max_recusion(self):

        bot = Bot(BotConfiguration())
        self.assertIsNotNone(bot)
        bot.configuration._default_response = "Sorry, I don't have an answer for that right now"
        bot.configuration._max_question_recursion = 0

        with self.assertRaises(Exception):
            bot.ask_question(self._client_context, "hello")
Exemplo n.º 15
0
    def test_get_exit_response_empty_string(self):

        bot_config = BotConfiguration()
        self.assertIsNotNone(bot_config)

        bot = Bot(bot_config)
        self.assertIsNotNone(bot)

        self.assertEquals("Bye!", bot.get_exit_response(self._client_context))
Exemplo n.º 16
0
    def test_get_initial_question_empty_string(self):

        bot_config = BotConfiguration()
        self.assertIsNotNone(bot_config)

        bot = Bot(bot_config)
        self.assertIsNotNone(bot)

        self.assertEquals("Hello", bot.get_initial_question(self._client_context))
Exemplo n.º 17
0
    def test_authenticator_with_empty_config(self):
        client_context = ClientContext(TestClient(), "console")
        client_context.bot = Bot(BotConfiguration())
        client_context.bot.configuration.conversations._max_histories = 3
        client_context.brain = client_context.bot.brain

        service = Authenticator(BrainSecurityConfiguration("authentication"))
        self.assertIsNotNone(service)
        self.assertIsNotNone(service.configuration)
        self.assertIsNone(service.get_default_denied_srai())
        self.assertFalse(service.authenticate(client_context))
Exemplo n.º 18
0
    def test_bot_init_blank(self):
        
        bot = Bot(BotConfiguration())

        self.assertIsNone(bot.spell_checker)
        self.assertIsNotNone(bot.brain)
        self.assertIsNotNone(bot.conversations)
        self.assertIsNotNone(bot.default_response)
        self.assertIsNotNone(bot.exit_response)
        self.assertIsNotNone(bot.initial_question)
        self.assertTrue(bot.override_properties)
        self.assertIsNotNone(bot.get_version_string)
Exemplo n.º 19
0
    def test_format_message_with_client_context(self):

        client = TestClient()

        bot_config = BotConfiguration()
        bot_config._section_name = "testbot"
        bot = Bot(bot_config, client)

        brain_config = BrainConfiguration()
        brain_config._section_name = "testbrain"
        brain = Brain(bot, brain_config)

        client_context = ClientContext(client, "testuser")
        client_context._bot = bot
        client_context._brain = brain

        msg = YLogger.format_message(client_context, "Test Message")
        self.assertIsNotNone(msg)
        self.assertEquals(
            "[testclient] [testbot] [testbrain] [testuser] - Test Message",
            msg)
Exemplo n.º 20
0
    def test_conversation(self):

        client_context = ClientContext(TestClient(), "testid")
        client_context.bot = Bot(BotConfiguration())
        client_context.bot.configuration.conversations._max_histories = 3
        client_context.brain = client_context.bot.brain

        conversation = Conversation(client_context)
        self.assertIsNotNone(conversation)
        self.assertEqual(0, len(conversation._questions))
        self.assertEqual(3, conversation._max_histories)
        self.assertEqual(1, len(conversation._properties))

        with self.assertRaises(Exception):
            conversation.current_question()
        with self.assertRaises(Exception):
            conversation.previous_nth_question(0)

        question1 = Question.create_from_text(
            client_context.brain.nlp.tokenizer, "Hello There")
        conversation.record_question(question1)
        self.assertEqual(question1, conversation.current_question())
        with self.assertRaises(Exception):
            conversation.previous_nth_question(1)

        question2 = Question.create_from_text(
            client_context.brain.nlp.tokenizer, "Hello There Again")
        conversation.record_question(question2)
        self.assertEqual(question2, conversation.current_question())
        self.assertEqual(question1, conversation.previous_nth_question(1))
        with self.assertRaises(Exception):
            conversation.previous_nth_question(3)

        question3 = Question.create_from_text(
            client_context.brain.nlp.tokenizer, "Hello There Again Again")
        conversation.record_question(question3)
        self.assertEqual(question3, conversation.current_question())
        self.assertEqual(question2, conversation.previous_nth_question(1))
        with self.assertRaises(Exception):
            conversation.previous_nth_question(4)

        # Max Histories for this test is 3
        # Therefore we should see the first question, pop of the stack

        question4 = Question.create_from_text(
            client_context.brain.nlp.tokenizer,
            "Hello There Again Again Again")
        conversation.record_question(question4)
        self.assertEqual(question4, conversation.current_question())
        self.assertEqual(question3, conversation.previous_nth_question(1))
        with self.assertRaises(Exception):
            conversation.previous_nth_question(5)
Exemplo n.º 21
0
    def test_service(self):
        client_context = ClientContext(TestClient(), "unknown")
        client_context.bot = Bot(BotConfiguration())
        client_context.bot.configuration.conversations._max_histories = 3
        client_context.brain = client_context.bot.brain

        service = BasicPassThroughAuthenticationService(
            BrainServiceConfiguration("authentication"))
        self.assertIsNotNone(service)
        self.assertIsNotNone(service.configuration)
        client_context._userid = "console"
        self.assertTrue(service.authenticate(client_context))
        client_context._userid = "anyone"
        self.assertTrue(service.authenticate(client_context))
Exemplo n.º 22
0
    def load_configuration(self, configuration_file, section, bot_root):
        if section is not None:
            bot_names = configuration_file.get_multi_option(
                section, "bot", missing_value="bot")
            first = True
            for name in bot_names:
                if first is True:
                    config = self._bot_configs[0]
                    first = False
                else:
                    config = BotConfiguration(name)
                    self._bot_configs.append(config)
                config.load_configuration(configuration_file, bot_root)

            self._license_keys = configuration_file.get_option(
                section, "license_keys")
            if self._license_keys is not None:
                self._license_keys = self.sub_bot_root(self._license_keys,
                                                       bot_root)

            self._bot_selector = configuration_file.get_option(
                section, "bot_selector")

            self._scheduler.load_config_section(configuration_file, section,
                                                bot_root)

            self._renderer = configuration_file.get_option(section, "renderer")

        else:
            YLogger.warning(
                self,
                "No bot name defined for client [%s], defaulting to 'bot'.",
                self.section_name)
            self._bot_configs[0]._section_name = "bot"
            self._bot_configs[0].load_configuration(configuration_file,
                                                    bot_root)
Exemplo n.º 23
0
    def test_without_data(self):
        yaml = YamlConfigurationFile()
        self.assertIsNotNone(yaml)
        yaml.load_from_text("""
        bot:
        """, ConsoleConfiguration(), ".")

        bot_config = BotConfiguration()
        bot_config.load_configuration(yaml, ".")

        self.assertEqual("Hello", bot_config.initial_question)
        self.assertEqual("", bot_config.initial_question_srai)
        self.assertEqual("", bot_config.default_response)
        self.assertEqual("", bot_config.default_response_srai)
        self.assertEqual("Bye!", bot_config.exit_response)
        self.assertEqual("", bot_config.exit_response_srai)
        self.assertEqual("", bot_config.empty_string)
        self.assertEqual(bot_config.max_question_recursion, 100)
        self.assertEqual(bot_config.max_question_timeout, -1)
        self.assertEqual(bot_config.max_search_depth, 100)
        self.assertEqual(bot_config.max_search_timeout, -1)
        self.assertTrue(bot_config.override_properties)
        self.assertIsNotNone(bot_config.spelling)
        self.assertIsNotNone(bot_config.conversations)
Exemplo n.º 24
0
    def test_config_init(self):
        arguments = MockArgumentParser()
        client = MockBotClient(arguments)

        configuration = unittest.mock.Mock()

        configuration.brain_config = [BotConfiguration()]

        configuration.bot_selector = "programr.clients.client.DefaultBotSelector"

        factory = BotFactory(client, configuration)
        self.assertIsNotNone(factory)

        bot = factory.select_bot()
        self.assertIsNotNone(bot)
        self.assertIsInstance(bot, Bot)
Exemplo n.º 25
0
    def test_bot_init_with_spellchecker(self):
        
        bot_config = BotConfiguration()
        bot_config.spelling._classname = "programr.spelling.norvig.NorvigSpellingChecker"
        bot_config.spelling._corpus = os.path.dirname(__file__) + os.sep + "test_corpus.txt"
        bot_config.spelling._check_before = True
        bot_config.spelling._check_and_retry = True
        bot = Bot(bot_config)
        self.assertIsNotNone(bot)

        test_sentence = Sentence(bot.brain.nlp.tokenizer, "locetion")
        bot.check_spelling_before(test_sentence)
        self.assertIsNotNone(test_sentence)
        self.assertEqual("LOCATION", test_sentence.text())

        test_sentence = Sentence(bot.brain.nlp.tokenizer, "locetion")
        response = bot.check_spelling_and_retry(self._client_context, test_sentence)
        self.assertIsNone(response)
Exemplo n.º 26
0
    def test_learn_simple(self):
        
        client_context1 = ClientContext(TestClient(), "testid")
        client_context1.bot = Bot(BotConfiguration())
        client_context1.brain = client_context1.bot.brain

        template = ET.fromstring("""
			<template>
				<learn>
				    <category>
				        <pattern>HELLO <eval>WORLD</eval> <iset>THERE, NOW</iset></pattern>
				        <template>HIYA</template>
				    </category>
				</learn>
			</template>
			""")

        ast = self._graph.parse_template_expression(template)
        self.assertIsNotNone(ast)
        self.assertIsInstance(ast, TemplateNode)
        self.assertIsNotNone(ast.children)
        self.assertEqual(len(ast.children), 1)

        learn_node = ast.children[0]
        self.assertIsNotNone(learn_node)
        self.assertIsInstance(learn_node, TemplateLearnNode)
        self.assertEqual(1, len(learn_node.children))
        self.assertIsInstance(learn_node.children[0], LearnCategory)
        self.assertIsNotNone(learn_node.children[0].pattern)
        self.assertIsInstance(learn_node.children[0].pattern, ET.Element)
        self.assertIsNotNone(learn_node.children[0].topic)
        self.assertIsInstance(learn_node.children[0].topic, ET.Element)
        self.assertIsNotNone(learn_node.children[0].that)
        self.assertIsInstance(learn_node.children[0].that, ET.Element)
        self.assertIsNotNone(learn_node.children[0].template)
        self.assertIsInstance(learn_node.children[0].template, TemplateNode)

        resolved = learn_node.resolve(client_context1)
        self.assertEqual(resolved, "")

        response = client_context1.bot.ask_question(client_context1, "HELLO WORLD THERE")
        self.assertEqual("HIYA", response)
Exemplo n.º 27
0
    def post_process(self, output_str):
        context = ClientContext(TestClient(), "testid")

        context.bot = Bot(config=BotConfiguration())
        context.brain = context.bot.brain
        context.bot.brain.denormals.process_splits([" dot com ", ".com"])
        context.bot.brain.denormals.process_splits([" atsign ", "@"])
        denormalize = DenormalizePostProcessor()
        punctuation = FormatPunctuationProcessor()
        numbers = FormatNumbersPostProcessor()
        multispaces = RemoveMultiSpacePostProcessor()
        emojize = EmojizePreProcessor()

        output_str = denormalize.process(context, output_str)
        output_str = punctuation.process(context, output_str)
        output_str = numbers.process(context, output_str)
        output_str = multispaces.process(context, output_str)
        output_str = emojize.process(context, output_str)

        return output_str
Exemplo n.º 28
0
    def setUp(self):
        bot_config = BotConfiguration()

        if os.name == 'posix':
            bot_config.brain_config[
                0].files.aiml_files._errors = DebugFileConfiguration(
                    "conversation", filename="/tmp/tmp-errors.txt.txt")
        elif os.name == 'nt':
            bot_config.brain_config[
                0].files.aiml_files._errors = DebugFileConfiguration(
                    "conversation",
                    filename='C:\Windows\Temp\\tmp-errors.txt.txt')
        else:
            raise Exception("Unknown os [%s]" % os.name)

        bot = Bot(bot_config)

        self.parser = bot.brain.aiml_parser
        self.parser.create_debug_storage(bot_config.brain_config[0])
        self.assertIsNotNone(self.parser)
Exemplo n.º 29
0
    def test_pre_cleanup(self):

        context = ClientContext(TestClient(), "testid")
        context.bot = Bot(config=BotConfiguration())
        context.brain = context.bot.brain
        test_str = "This is my Location!"

        punctuation_processor = RemovePunctuationPreProcessor()
        test_str = punctuation_processor.process(context, test_str)
        self.assertEqual("This is my Location", test_str)

        normalize_processor = NormalizePreProcessor()
        test_str = normalize_processor.process(context, test_str)
        self.assertEqual("This is my Location", test_str)

        toupper_processor = ToUpperPreProcessor()
        test_str = toupper_processor.process(context, test_str)
        self.assertEqual("THIS IS MY LOCATION", test_str)

        demojize_processpr = DemojizePreProcessor()
        test_str = demojize_processpr.process(context, test_str)
        self.assertEqual(test_str, test_str)
Exemplo n.º 30
0
    def test_bot_with_conversation(self):
        
        bot = Bot(BotConfiguration())
        self.assertIsNotNone(bot)

        self.assertFalse(bot.has_conversation(self._client_context))

        response = bot.ask_question(self._client_context, "hello")
        self.assertIsNotNone(response)
        self.assertTrue(bot.has_conversation(self._client_context))

        response = bot.ask_question(self._client_context, "hello")
        self.assertIsNotNone(response)
        self.assertTrue(bot.has_conversation(self._client_context))

        client_context2 = ClientContext(TestClient(), "testid2")
        client_context2._bot = bot
        client_context2._brain = self._client_context.bot.brain

        response = bot.ask_question(client_context2, "hello")
        self.assertIsNotNone(response)
        self.assertTrue(bot.has_conversation(client_context2))