示例#1
0
class TestDynamicTwitterStream(TestCase):
    def setUp(self):

        # Mock tweepy.Stream
        self.stream_patcher = mock.patch('tweepy.Stream')
        self.MockTweepyStream = self.stream_patcher.start()
        self.tweepy_stream_instance = mock.Mock()
        self.MockTweepyStream.return_value = self.tweepy_stream_instance

        # Mock the supporting objects
        self.auth = mock.Mock()
        self.listener = mock.Mock()
        self.checker = mock.Mock()

        # For controlling the tracking terms
        self.term_list = []
        self.checker.tracking_terms.return_value = self.term_list

        self.stop_timeout = DynamicTwitterStream.STOP_TIMEOUT
        DynamicTwitterStream.STOP_TIMEOUT = 0
        self.retry_count = 7

        # Create a dynamic twitter stream
        self.stream = DynamicTwitterStream(auth=self.auth,
                                           listener=self.listener,
                                           term_checker=self.checker,
                                           retry_count=self.retry_count)

    def tearDown(self):
        self.stream_patcher.stop()

        # Restore the normal stop timeout
        DynamicTwitterStream.STOP_TIMEOUT = self.stop_timeout

    def test_start_stream_no_terms(self):

        # Start the stream without a term
        self.stream.start_stream()

        # Should check the list of terms
        self.checker.tracking_terms.assert_called_once_with()

        # A stream should NOT have been created, because no terms yet
        self.MockTweepyStream.assert_has_calls([])

    def test_start_unfiltered_no_terms(self):
        # Create an unfiltered stream instead
        self.stream = DynamicTwitterStream(auth=self.auth,
                                           listener=self.listener,
                                           term_checker=self.checker,
                                           retry_count=self.retry_count,
                                           unfiltered=True)
        
        # Start the stream without a term
        self.stream.start_stream()

        # Should check the list of terms
        self.checker.tracking_terms.assert_called_once_with()
        
        # But it should a stream even without any terms
        self.MockTweepyStream.assert_called_once_with(self.auth, self.listener,
                                                      stall_warnings=True,
                                                      timeout=90,
                                                      retry_count=self.retry_count)

        # It should be using the sample endpoint
        self.tweepy_stream_instance.sample.assert_called_once_with(async=True, languages=None)        

    def test_start_with_languages(self):

        # Create a stream with languages
        languages = ['en', 'fr']
        self.stream = DynamicTwitterStream(auth=self.auth,
                                           listener=self.listener,
                                           term_checker=self.checker,
                                           retry_count=self.retry_count,
                                           unfiltered=True,
                                           languages=languages)
        
        # Start the stream without a term
        self.stream.start_stream()

        # It should be using the sample endpoint with languages
        self.tweepy_stream_instance.sample.assert_called_once_with(async=True, languages=languages)


    def test_start_stream_with_terms(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        # Should check the list of terms
        self.checker.tracking_terms.assert_called_once_with()

        # Should create a Stream instance
        self.MockTweepyStream.assert_called_once_with(self.auth, self.listener,
                                                      stall_warnings=True,
                                                      timeout=90,
                                                      retry_count=self.retry_count)
        # Should start the filter with the terms
        self.tweepy_stream_instance.filter.assert_called_once_with(track=self.term_list, async=True, languages=None)


    def test_stop_stream_not_started(self):

        self.stream.stop_stream()

        # No attempt to disconnect stream that isn't started
        self.tweepy_stream_instance.disconnect.assert_has_calls([])


    def test_stop_stream_started(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        self.stream.stop_stream()

        # Should try to disconnect tweepy stream
        self.tweepy_stream_instance.disconnect.assert_called_once_with()

    def test_update_stream_terms_unchanged(self):

        self.checker.check.return_value = False

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        self.stream.update_stream()

        # Should have checked if terms changed
        self.checker.check.assert_called_once_with()

        # Should NOT have stopped the old stream
        self.assertEqual(self.stream.stop_stream.call_count, 0)

        # Should NOT have started a new stream
        self.assertEqual(self.stream.start_stream.call_count, 0)

    def test_update_stream_terms_changed(self):

        self.checker.check.return_value = True

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        self.stream.update_stream()

        # Should have checked if terms changed
        self.checker.check.assert_called_once_with()

        # Should have stopped the old stream
        self.stream.stop_stream.assert_called_once_with()

        # Should have started a new stream
        self.stream.start_stream.assert_called_once_with()

    def test_update_stream_after_error(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        # Simulate a dead stream
        self.tweepy_stream_instance.running = False
        self.listener.error = 500

        self.stream.update_stream()

        # Should have stopped the old stream
        self.stream.stop_stream.assert_called_once_with()

        # Should have started a new stream
        self.stream.start_stream.assert_called_once_with()

        # Should have turned off the error
        self.assertFalse(self.listener.error)

    def test_update_stream_after_exception(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        # Simulate an exception inside Tweepy
        self.tweepy_stream_instance.running = False
        self.listener.streaming_exception = Exception("testing")

        self.stream.update_stream()

        # Should have stopped the old stream
        self.stream.stop_stream.assert_called_once_with()

        # Should have started a new stream
        self.stream.start_stream.assert_called_once_with()

        # Should have turned off the exception
        self.assertFalse(self.listener.streaming_exception)

    def test_handle_exceptions(self):

        self.listener.streaming_exception = None

        try:
            self.stream.handle_exceptions()
        except Exception:
            self.fail("Raised exception when no streaming exception set")

        self.listener.streaming_exception = Exception("testing")
        self.assertRaises(Exception, self.stream.handle_exceptions)

    def test_clears_exceptions(self):

        self.listener.streaming_exception = Exception("testing")
        try:
            self.stream.handle_exceptions()
        except:
            pass

        self.assertEquals(self.listener.streaming_exception, None)


    def test_stop_polling(self):

        # Mock some supporting methods we test separately
        self.stream.update_stream = mock.Mock()
        self.stream.handle_exceptions = mock.Mock()

        # This should poll every 1 second
        thread = threading.Thread(target=self.stream.start_polling, args=[1])
        thread.start()

        waits = 0
        # Wait for a maximum of 3 seconds (ish), or until the loop has run at least once
        while self.stream.update_stream.call_count < 2 and waits < 12:
            print "Waiting..."
            time.sleep(0.25)
            waits += 1

        self.assertTrue(self.stream.polling)

        # Try to stop the thread
        self.stream.stop_polling()

        self.assertFalse(self.stream.polling)

        # Wait for a maximimum of 2 seconds
        thread.join(timeout=2)

        self.assertTrue(self.stream.update_stream.call_count >= 1, "Checked for stream/term updates")
        self.assertTrue(self.stream.handle_exceptions.call_count >= 1, "Checked for stream exceptions")
示例#2
0
class TestDynamicTwitterStream(TestCase):
    def setUp(self):

        # Mock tweepy.Stream
        self.stream_patcher = mock.patch('tweepy.Stream')
        self.MockTweepyStream = self.stream_patcher.start()
        self.tweepy_stream_instance = mock.Mock()
        self.MockTweepyStream.return_value = self.tweepy_stream_instance

        # Mock the supporting objects
        self.auth = mock.Mock()
        self.listener = mock.Mock()
        self.checker = mock.Mock()

        # For controlling the tracking terms
        self.term_list = []
        self.checker.tracking_terms.return_value = self.term_list

        self.stop_timeout = DynamicTwitterStream.STOP_TIMEOUT
        DynamicTwitterStream.STOP_TIMEOUT = 0
        self.retry_count = 7

        # Create a dynamic twitter stream
        self.stream = DynamicTwitterStream(auth=self.auth,
                                           listener=self.listener,
                                           term_checker=self.checker,
                                           retry_count=self.retry_count)

    def tearDown(self):
        self.stream_patcher.stop()

        # Restore the normal stop timeout
        DynamicTwitterStream.STOP_TIMEOUT = self.stop_timeout

    def test_start_stream_no_terms(self):

        # Start the stream without a term
        self.stream.start_stream()

        # Should check the list of terms
        self.checker.tracking_terms.assert_called_once_with()

        # A stream should NOT have been created, because no terms yet
        self.MockTweepyStream.assert_has_calls([])

    def test_start_unfiltered_no_terms(self):
        # Create an unfiltered stream instead
        self.stream = DynamicTwitterStream(auth=self.auth,
                                           listener=self.listener,
                                           term_checker=self.checker,
                                           retry_count=self.retry_count,
                                           unfiltered=True)

        # Start the stream without a term
        self.stream.start_stream()

        # Should check the list of terms
        self.checker.tracking_terms.assert_called_once_with()

        # But it should a stream even without any terms
        self.MockTweepyStream.assert_called_once_with(
            self.auth,
            self.listener,
            stall_warnings=True,
            timeout=90,
            retry_count=self.retry_count)

        # It should be using the sample endpoint
        self.tweepy_stream_instance.sample.assert_called_once_with(
            is_async=True, languages=None)

    def test_start_with_languages(self):

        # Create a stream with languages
        languages = ['en', 'fr']
        self.stream = DynamicTwitterStream(auth=self.auth,
                                           listener=self.listener,
                                           term_checker=self.checker,
                                           retry_count=self.retry_count,
                                           unfiltered=True,
                                           languages=languages)

        # Start the stream without a term
        self.stream.start_stream()

        # It should be using the sample endpoint with languages
        self.tweepy_stream_instance.sample.assert_called_once_with(
            is_async=True, languages=languages)

    def test_start_stream_with_terms(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        # Should check the list of terms
        self.checker.tracking_terms.assert_called_once_with()

        # Should create a Stream instance
        self.MockTweepyStream.assert_called_once_with(
            self.auth,
            self.listener,
            stall_warnings=True,
            timeout=90,
            retry_count=self.retry_count)
        # Should start the filter with the terms
        self.tweepy_stream_instance.filter.assert_called_once_with(
            track=self.term_list, is_async=True, languages=None)

    def test_stop_stream_not_started(self):

        self.stream.stop_stream()

        # No attempt to disconnect stream that isn't started
        self.tweepy_stream_instance.disconnect.assert_has_calls([])

    def test_stop_stream_started(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        self.stream.stop_stream()

        # Should try to disconnect tweepy stream
        self.tweepy_stream_instance.disconnect.assert_called_once_with()

    def test_update_stream_terms_unchanged(self):

        self.checker.check.return_value = False

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        self.stream.update_stream()

        # Should have checked if terms changed
        self.checker.check.assert_called_once_with()

        # Should NOT have stopped the old stream
        self.assertEqual(self.stream.stop_stream.call_count, 0)

        # Should NOT have started a new stream
        self.assertEqual(self.stream.start_stream.call_count, 0)

    def test_update_stream_terms_changed(self):

        self.checker.check.return_value = True

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        self.stream.update_stream()

        # Should have checked if terms changed
        self.checker.check.assert_called_once_with()

        # Should have stopped the old stream
        self.stream.stop_stream.assert_called_once_with()

        # Should have started a new stream
        self.stream.start_stream.assert_called_once_with()

    def test_update_stream_after_error(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        # Simulate a dead stream
        self.tweepy_stream_instance.running = False
        self.listener.error = 500

        self.stream.update_stream()

        # Should have stopped the old stream
        self.stream.stop_stream.assert_called_once_with()

        # Should have started a new stream
        self.stream.start_stream.assert_called_once_with()

        # Should have turned off the error
        self.assertFalse(self.listener.error)

    def test_update_stream_after_exception(self):

        # Start the stream with a term
        self.term_list.append("hello")
        self.stream.start_stream()

        self.stream.start_stream = mock.Mock()
        self.stream.stop_stream = mock.Mock()

        # Simulate an exception inside Tweepy
        self.tweepy_stream_instance.running = False
        self.listener.streaming_exception = Exception("testing")

        self.stream.update_stream()

        # Should have stopped the old stream
        self.stream.stop_stream.assert_called_once_with()

        # Should have started a new stream
        self.stream.start_stream.assert_called_once_with()

        # Should have turned off the exception
        self.assertFalse(self.listener.streaming_exception)

    def test_handle_exceptions(self):

        self.listener.streaming_exception = None

        try:
            self.stream.handle_exceptions()
        except Exception:
            self.fail("Raised exception when no streaming exception set")

        self.listener.streaming_exception = Exception("testing")
        self.assertRaises(Exception, self.stream.handle_exceptions)

    def test_clears_exceptions(self):

        self.listener.streaming_exception = Exception("testing")
        try:
            self.stream.handle_exceptions()
        except:
            pass

        self.assertEqual(self.listener.streaming_exception, None)

    def test_stop_polling(self):

        # Mock some supporting methods we test separately
        self.stream.update_stream = mock.Mock()
        self.stream.handle_exceptions = mock.Mock()

        # This should poll every 1 second
        thread = threading.Thread(target=self.stream.start_polling, args=[1])
        thread.start()

        waits = 0
        # Wait for a maximum of 3 seconds (ish), or until the loop has run at least once
        while self.stream.update_stream.call_count < 2 and waits < 12:
            print("Waiting...")
            time.sleep(0.25)
            waits += 1

        self.assertTrue(self.stream.polling)

        # Try to stop the thread
        self.stream.stop_polling()

        self.assertFalse(self.stream.polling)

        # Wait for a maximimum of 2 seconds
        thread.join(timeout=2)

        self.assertTrue(self.stream.update_stream.call_count >= 1,
                        "Checked for stream/term updates")
        self.assertTrue(self.stream.handle_exceptions.call_count >= 1,
                        "Checked for stream exceptions")