News + RSS: Mock time.time() instead of using time.sleep() in tests.

Saves 40s over the ~5min test suite.
This commit is contained in:
Valentin Lorentz 2019-10-05 12:12:46 +02:00
parent 3c42ce0861
commit a4665803fa
3 changed files with 60 additions and 45 deletions

View File

@ -50,10 +50,7 @@ class NewsTestCase(ChannelPluginTestCase):
self.assertRegexp('news', 'subject.*subject2') self.assertRegexp('news', 'subject.*subject2')
self.assertNotError('add 5 subject3: foo3') self.assertNotError('add 5 subject3: foo3')
self.assertRegexp('news', 'subject3') self.assertRegexp('news', 'subject3')
print() timeFastForward(6)
print('Sleeping to expire the news item (testAddnews)')
time.sleep(6)
print('Done sleeping.')
self.assertNotRegexp('news', 'subject3') self.assertNotRegexp('news', 'subject3')
def testNews(self): def testNews(self):
@ -79,10 +76,7 @@ class NewsTestCase(ChannelPluginTestCase):
self.assertRegexp('old', 'No old news') self.assertRegexp('old', 'No old news')
self.assertNotError('add 5 foo: bar') self.assertNotError('add 5 foo: bar')
self.assertRegexp('old', 'No old news') self.assertRegexp('old', 'No old news')
print() timeFastForward(6)
print('Sleeping to expire the news item (testOldnews)')
time.sleep(6)
print('Done sleeping.')
self.assertNotError('old') self.assertNotError('old')

View File

@ -82,7 +82,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testInitialAnnounceNewest(self): def testInitialAnnounceNewest(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
time.sleep(1.1) timeFastForward(1.1)
try: try:
with conf.supybot.plugins.RSS.sortFeedItems.context('newestFirst'): with conf.supybot.plugins.RSS.sortFeedItems.context('newestFirst'):
with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(1): with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(1):
@ -97,7 +97,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testInitialAnnounceOldest(self): def testInitialAnnounceOldest(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
time.sleep(1.1) timeFastForward(1.1)
try: try:
with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(1): with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(1):
with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'): with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'):
@ -112,7 +112,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testNoInitialAnnounce(self): def testNoInitialAnnounce(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(0): with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(0):
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -126,7 +126,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testAnnounce(self): def testAnnounce(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
self.assertError('rss announce add xkcd') self.assertError('rss announce add xkcd')
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -134,12 +134,12 @@ class RSSTestCase(ChannelPluginTestCase):
self.assertNotError(' ') self.assertNotError(' ')
with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'): with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'):
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNoResponse(' ') self.assertNoResponse(' ')
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
self.assertNoResponse(' ') self.assertNoResponse(' ')
time.sleep(1.1) timeFastForward(1.1)
self.assertRegexp(' ', 'Chaos') self.assertRegexp(' ', 'Chaos')
self.assertRegexp(' ', 'Telescopes') self.assertRegexp(' ', 'Telescopes')
self.assertNoResponse(' ') self.assertNoResponse(' ')
@ -151,7 +151,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testMaxAnnounces(self): def testMaxAnnounces(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
self.assertError('rss announce add xkcd') self.assertError('rss announce add xkcd')
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -160,12 +160,12 @@ class RSSTestCase(ChannelPluginTestCase):
with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'): with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'):
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
with conf.supybot.plugins.RSS.maximumAnnounceHeadlines.context(1): with conf.supybot.plugins.RSS.maximumAnnounceHeadlines.context(1):
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNoResponse(' ') self.assertNoResponse(' ')
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
self.assertNoResponse(' ') self.assertNoResponse(' ')
time.sleep(1.1) timeFastForward(1.1)
self.assertRegexp(' ', 'Telescopes') self.assertRegexp(' ', 'Telescopes')
self.assertNoResponse(' ') self.assertNoResponse(' ')
finally: finally:
@ -176,17 +176,17 @@ class RSSTestCase(ChannelPluginTestCase):
def testAnnounceAnonymous(self): def testAnnounceAnonymous(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
self.assertNotError('rss announce add http://xkcd.com/rss.xml') self.assertNotError('rss announce add http://xkcd.com/rss.xml')
self.assertNotError(' ') self.assertNotError(' ')
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNoResponse(' ') self.assertNoResponse(' ')
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
self.assertNoResponse(' ') self.assertNoResponse(' ')
time.sleep(1.1) timeFastForward(1.1)
self.assertRegexp(' ', 'Telescopes') self.assertRegexp(' ', 'Telescopes')
finally: finally:
self._feedMsg('rss announce remove http://xkcd.com/rss.xml') self._feedMsg('rss announce remove http://xkcd.com/rss.xml')
@ -196,7 +196,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testAnnounceReload(self): def testAnnounceReload(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -204,7 +204,7 @@ class RSSTestCase(ChannelPluginTestCase):
self.assertNotError(' ') self.assertNotError(' ')
self.assertNotError('reload RSS') self.assertNotError('reload RSS')
self.assertNoResponse(' ') self.assertNoResponse(' ')
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
finally: finally:
self._feedMsg('rss announce remove xkcd') self._feedMsg('rss announce remove xkcd')
@ -214,7 +214,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testReload(self): def testReload(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -232,7 +232,7 @@ class RSSTestCase(ChannelPluginTestCase):
# https://github.com/ProgVal/Limnoria/issues/922 # https://github.com/ProgVal/Limnoria/issues/922
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -247,7 +247,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testReannounce(self): def testReannounce(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
self.assertError('rss announce add xkcd') self.assertError('rss announce add xkcd')
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
@ -256,16 +256,16 @@ class RSSTestCase(ChannelPluginTestCase):
with conf.supybot.plugins.RSS.waitPeriod.context(1): with conf.supybot.plugins.RSS.waitPeriod.context(1):
with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(1): with conf.supybot.plugins.RSS.initialAnnounceHeadlines.context(1):
with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'): with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'):
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNoResponse(' ') self.assertNoResponse(' ')
self._feedMsg('rss announce remove xkcd') self._feedMsg('rss announce remove xkcd')
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNotError('rss announce add xkcd') self.assertNotError('rss announce add xkcd')
time.sleep(1.1) timeFastForward(1.1)
self.assertRegexp(' ', 'Chaos') self.assertRegexp(' ', 'Chaos')
self.assertRegexp(' ', 'Telescopes') self.assertRegexp(' ', 'Telescopes')
self.assertNoResponse(' ') self.assertNoResponse(' ')
@ -277,7 +277,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testFeedSpecificFormat(self): def testFeedSpecificFormat(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
self.assertNotError('rss add xkcd http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd http://xkcd.com/rss.xml')
self.assertNotError('rss add xkcdsec https://xkcd.com/rss.xml') self.assertNotError('rss add xkcdsec https://xkcd.com/rss.xml')
@ -293,7 +293,7 @@ class RSSTestCase(ChannelPluginTestCase):
def testFeedSpecificWaitPeriod(self): def testFeedSpecificWaitPeriod(self):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_old) feedparser._open_resource = constant(xkcd_old)
time.sleep(1.1) timeFastForward(1.1)
try: try:
self.assertNotError('rss add xkcd1 http://xkcd.com/rss.xml') self.assertNotError('rss add xkcd1 http://xkcd.com/rss.xml')
self.assertNotError('rss announce add xkcd1') self.assertNotError('rss announce add xkcd1')
@ -303,16 +303,16 @@ class RSSTestCase(ChannelPluginTestCase):
self.assertNotError(' ') self.assertNotError(' ')
with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'): with conf.supybot.plugins.RSS.sortFeedItems.context('oldestFirst'):
with conf.supybot.plugins.RSS.feeds.xkcd1.waitPeriod.context(1): with conf.supybot.plugins.RSS.feeds.xkcd1.waitPeriod.context(1):
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
self.assertNoResponse(' ') self.assertNoResponse(' ')
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
self.assertNoResponse(' ') self.assertNoResponse(' ')
time.sleep(1.1) timeFastForward(1.1)
self.assertRegexp(' ', 'xkcd1.*Chaos') self.assertRegexp(' ', 'xkcd1.*Chaos')
self.assertRegexp(' ', 'xkcd1.*Telescopes') self.assertRegexp(' ', 'xkcd1.*Telescopes')
self.assertNoResponse(' ') self.assertNoResponse(' ')
time.sleep(1.1) timeFastForward(1.1)
self.assertNoResponse(' ') self.assertNoResponse(' ')
finally: finally:
self._feedMsg('rss announce remove xkcd1') self._feedMsg('rss announce remove xkcd1')
@ -322,7 +322,7 @@ class RSSTestCase(ChannelPluginTestCase):
feedparser._open_resource = old_open feedparser._open_resource = old_open
def testDescription(self): def testDescription(self):
time.sleep(1.1) timeFastForward(1.1)
with conf.supybot.plugins.RSS.format.context('$description'): with conf.supybot.plugins.RSS.format.context('$description'):
old_open = feedparser._open_resource old_open = feedparser._open_resource
feedparser._open_resource = constant(xkcd_new) feedparser._open_resource = constant(xkcd_new)
@ -336,7 +336,7 @@ class RSSTestCase(ChannelPluginTestCase):
# This combination will cause the RSS command to show the last parser # This combination will cause the RSS command to show the last parser
# error. # error.
old_open = feedparser._open_resource old_open = feedparser._open_resource
time.sleep(1.1) timeFastForward(1.1)
feedparser._open_resource = constant(not_well_formed) feedparser._open_resource = constant(not_well_formed)
try: try:
self.assertRegexp('rss http://example.com/', self.assertRegexp('rss http://example.com/',
@ -346,7 +346,7 @@ class RSSTestCase(ChannelPluginTestCase):
if network: if network:
def testRssinfo(self): def testRssinfo(self):
time.sleep(1.1) timeFastForward(1.1)
self.assertNotError('rss info %s' % url) self.assertNotError('rss info %s' % url)
self.assertNotError('rss add advogato %s' % url) self.assertNotError('rss add advogato %s' % url)
self.assertNotError('rss info advogato') self.assertNotError('rss info advogato')
@ -354,12 +354,12 @@ class RSSTestCase(ChannelPluginTestCase):
self.assertNotError('rss remove advogato') self.assertNotError('rss remove advogato')
def testRssinfoDoesTimeProperly(self): def testRssinfoDoesTimeProperly(self):
time.sleep(1.1) timeFastForward(1.1)
self.assertNotRegexp('rss info http://slashdot.org/slashdot.rss', self.assertNotRegexp('rss info http://slashdot.org/slashdot.rss',
'-1 years') '-1 years')
def testAnnounceAdd(self): def testAnnounceAdd(self):
time.sleep(1.1) timeFastForward(1.1)
self.assertNotError('rss add advogato %s' % url) self.assertNotError('rss add advogato %s' % url)
self.assertNotError('rss announce add advogato') self.assertNotError('rss announce add advogato')
self.assertNotRegexp('rss announce', r'ValueError') self.assertNotRegexp('rss announce', r'ValueError')
@ -367,13 +367,13 @@ class RSSTestCase(ChannelPluginTestCase):
self.assertNotError('rss remove advogato') self.assertNotError('rss remove advogato')
def testRss(self): def testRss(self):
time.sleep(1.1) timeFastForward(1.1)
self.assertNotError('rss %s' % url) self.assertNotError('rss %s' % url)
m = self.assertNotError('rss %s 2' % url) m = self.assertNotError('rss %s 2' % url)
self.failUnless(m.args[1].count(' | ') == 1) self.failUnless(m.args[1].count(' | ') == 1)
def testRssAdd(self): def testRssAdd(self):
time.sleep(1.1) timeFastForward(1.1)
self.assertNotError('rss add advogato %s' % url) self.assertNotError('rss add advogato %s' % url)
self.assertNotError('advogato') self.assertNotError('advogato')
self.assertNotError('rss advogato') self.assertNotError('rss advogato')
@ -383,7 +383,7 @@ class RSSTestCase(ChannelPluginTestCase):
self.assertError('rss advogato') self.assertError('rss advogato')
def testNonAsciiFeeds(self): def testNonAsciiFeeds(self):
time.sleep(1.1) timeFastForward(1.1)
self.assertNotError('rss http://www.heise.de/newsticker/heise.rdf') self.assertNotError('rss http://www.heise.de/newsticker/heise.rdf')
self.assertNotError('rss info http://br-linux.org/main/index.xml') self.assertNotError('rss info http://br-linux.org/main/index.xml')

View File

@ -74,6 +74,25 @@ def cachingGetHelp(method, name=None, doc=None):
return lastGetHelp return lastGetHelp
callbacks.getHelp = cachingGetHelp callbacks.getHelp = cachingGetHelp
real_time = time.time
mock_time_offset = 0
def mockTime():
"""Wrapper for time.time() that adds an offset, eg. for skipping after a
timeout expired."""
return real_time() + mock_time_offset
def timeFastForward(extra_offset):
global mock_time_offset
mock_time_offset += extra_offset
def setupMockTime():
mock_time_offset = 0
time.time = mockTime
def teardownMockTime():
time.time = real_time
def retry(tries=3): def retry(tries=3):
assert tries > 0 assert tries > 0
def decorator(f): def decorator(f):
@ -133,11 +152,13 @@ class SupyTestCase(unittest.TestCase):
log.critical('Beginning test case %s', self.id()) log.critical('Beginning test case %s', self.id())
threads = [t.getName() for t in threading.enumerate()] threads = [t.getName() for t in threading.enumerate()]
log.critical('Threads: %L', threads) log.critical('Threads: %L', threads)
setupMockTime()
unittest.TestCase.setUp(self) unittest.TestCase.setUp(self)
def tearDown(self): def tearDown(self):
for irc in world.ircs[:]: for irc in world.ircs[:]:
irc._reallyDie() irc._reallyDie()
teardownMockTime()
if sys.version_info < (2, 7, 0): if sys.version_info < (2, 7, 0):
def assertIn(self, member, container, msg=None): def assertIn(self, member, container, msg=None):
@ -288,9 +309,9 @@ class PluginTestCase(SupyTestCase):
if not expectException and self.myVerbose >= verbosity.EXCEPTIONS: if not expectException and self.myVerbose >= verbosity.EXCEPTIONS:
conf.supybot.log.stdout.setValue(True) conf.supybot.log.stdout.setValue(True)
self.irc.feedMsg(msg) self.irc.feedMsg(msg)
fed = time.time() fed = real_time()
response = self.irc.takeMsg() response = self.irc.takeMsg()
while response is None and time.time() - fed < timeout: while response is None and real_time() - fed < timeout:
time.sleep(0.01) # So it doesn't suck up 100% cpu. time.sleep(0.01) # So it doesn't suck up 100% cpu.
drivers.run() drivers.run()
response = self.irc.takeMsg() response = self.irc.takeMsg()
@ -487,9 +508,9 @@ class ChannelPluginTestCase(PluginTestCase):
if self.myVerbose >= verbosity.MESSAGES: if self.myVerbose >= verbosity.MESSAGES:
print('Feeding: %r' % msg) print('Feeding: %r' % msg)
self.irc.feedMsg(msg) self.irc.feedMsg(msg)
fed = time.time() fed = real_time()
response = self.irc.takeMsg() response = self.irc.takeMsg()
while response is None and time.time() - fed < timeout: while response is None and real_time() - fed < timeout:
time.sleep(0.1) time.sleep(0.1)
drivers.run() drivers.run()
response = self.irc.takeMsg() response = self.irc.takeMsg()