jenkins-bot has submitted this change and it was merged.
Change subject: [FEAT] tests: Generic reading bot class test case
......................................................................
[FEAT] tests: Generic reading bot class test case
For tests which use a Bot class and also userPut (or similar) this test case
can be used as it monkey patches '_save_page' to prevent actually saving the
page.
Change-Id: Iaec972f813f2470d1f2e51fde8d59b29d929925c
---
M tests/bot_tests.py
M tests/disambredir_tests.py
2 files changed, 90 insertions(+), 24 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/tests/bot_tests.py b/tests/bot_tests.py
index b2a9a7c..4764e79 100644
--- a/tests/bot_tests.py
+++ b/tests/bot_tests.py
@@ -14,7 +14,81 @@
import pywikibot
import pywikibot.bot
-from tests.aspects import unittest, DefaultSiteTestCase, SiteAttributeTestCase
+from tests.aspects import (
+ unittest, DefaultSiteTestCase, SiteAttributeTestCase, TestCase,
+)
+
+
+class FakeSaveBotTestCase(TestCase):
+
+ """
+ An abstract test case which patches the bot class to not actually write.
+
+ It redirects the bot's _save_page to it's own C{bot_save} method. Currently
+ userPut, put_current and user_edit_entity call it. By default it'll call
+ the original method but replace the function called to actually save the
+ page by C{page_save}. It patches the bot class as soon as this class'
+ attribute bot is defined. It also sets the bot's 'always' option to True to
+ avoid user interaction.
+
+ The C{bot_save} method compares the save counter before the call and
asserts
+ that it has increased by one after the call. It also stores locally in
+ C{save_called} if C{page_save} has been called. If C{bot_save} or
+ C{page_save} are implemented they should call super's method at some point
+ to make sure these assertions work. At C{tearDown} it checks that the pages
+ are saved often enough. The attribute C{default_assert_saves} defines the
+ number of saves which must happen and compares it to the difference using
+ the save counter. It is possible to define C{assert_saves} after C{setUp}
to
+ overwrite the default value for certain tests. By default the number of
+ saves it asserts are 1. Additionally C{save_called} increases by 1 on each
+ call of C{page_save} and should be equal to C{assert_saves}.
+
+ This means if the bot class actually does other writes, like using
+ L{pywikibot.page.Page.save} manually, it'll still write.
+ """
+
+ @property
+ def bot(self):
+ """Get the current bot."""
+ return self._bot
+
+ @bot.setter
+ def bot(self, value):
+ """Set and patch the current bot."""
+ assert value._save_page != self.bot_save, 'bot may not be patched.'
+ self._bot = value
+ self._bot.options['always'] = True
+ self._original = self._bot._save_page
+ self._bot._save_page = self.bot_save
+ self._old_counter = self._bot._save_counter
+
+ def setUp(self):
+ """Set up test by reseting the counters."""
+ super(FakeSaveBotTestCase, self).setUp()
+ self.assert_saves = getattr(self, 'default_assert_saves', 1)
+ self.save_called = 0
+
+ def tearDown(self):
+ """Tear down by asserting the counters."""
+ self.assertEqual(self._bot._save_counter,
+ self._old_counter + self.assert_saves)
+ self.assertEqual(self.save_called, self.assert_saves)
+ super(FakeSaveBotTestCase, self).tearDown()
+
+ def bot_save(self, page, func, *args, **kwargs):
+ """Handle when bot's userPut was called."""
+ self.assertGreaterEqual(self._bot._save_counter, 0)
+ old_counter = self._bot._save_counter
+ old_local_cnt = self.save_called
+ result = self._original(page, self.page_save, *args, **kwargs)
+ self.assertEqual(self._bot._save_counter, old_counter + 1)
+ self.assertEqual(self.save_called, old_local_cnt + 1)
+ self.assertGreater(self._bot._save_counter, self._old_counter)
+ return result
+
+ def page_save(self, *args, **kwargs):
+ """Handle when bot calls the page's save method."""
+ self.save_called += 1
class TestBotTreatExit(object):
diff --git a/tests/disambredir_tests.py b/tests/disambredir_tests.py
index 5b34e47..5e260c7 100644
--- a/tests/disambredir_tests.py
+++ b/tests/disambredir_tests.py
@@ -18,11 +18,12 @@
from scripts import disambredir
-from tests.aspects import unittest, TestCase
+from tests.aspects import unittest
+from tests.bot_tests import FakeSaveBotTestCase
from tests.utils import fixed_generator
-class TestDisambigurationRedirectBot(TestCase):
+class TestDisambigurationRedirectBot(FakeSaveBotTestCase):
"""
Test cases for DisambigurationRedirectBot.
@@ -62,70 +63,61 @@
def setUpClass(cls):
"""Initialize page variable."""
super(TestDisambigurationRedirectBot, cls).setUpClass()
+ # Patch the page to be independent of the actual site
cls.page = pywikibot.Page(cls.site, 'User:BobBot/Test disambig')
+ cls.page.linkedPages = fixed_generator(
+ [pywikibot.Page(cls.site, 'User:BobBot/Redir'),
+ pywikibot.Page(cls.site, 'Main Page')])
+
+ def bot_save(self, page, *args, **kwargs):
+ """Check if the page matches."""
+ self.assertIs(page, self.page)
+ return super(TestDisambigurationRedirectBot, self).bot_save(
+ page, *args, **kwargs)
def setUp(self):
"""Set up the test page."""
- def _save_page(*args, **kwargs):
- self.assertIs(args[0], self.page)
- self.save_called = True
- return # avert actually saving
-
super(TestDisambigurationRedirectBot, self).setUp()
self.page.text = ('[[User:BobBot/Redir#Foo|Bar]]\n'
'[[User:BobBot/Redir|Baz]]\n'
'[[Main Page|Label]]\n')
self.bot = disambredir.DisambiguationRedirectBot(generator=[self.page])
- self.bot.options['always'] = True
- # Patch the page and bot to not actually save anything
- self.page.linkedPages = fixed_generator(
- [pywikibot.Page(self.site, 'User:BobBot/Redir'),
- pywikibot.Page(self.site, 'Main Page')])
- self.save_called = False
- self.bot._save_page = _save_page
def test_unchanged(self):
"""Test no change."""
+ # No changes needed, won't call the save method
+ self.assert_saves = 0
self._patch_create_callback('n')
- self.assertFalse(self.save_called)
self.bot.run()
self.assertEqual(self.page.text,
'[[User:BobBot/Redir#Foo|Bar]]\n'
'[[User:BobBot/Redir|Baz]]\n'
'[[Main Page|Label]]\n')
- # No changes needed, won't call the save method
- self.assertFalse(self.save_called)
def test_unlink(self):
"""Test unlinking."""
self._patch_create_callback('u')
- self.assertFalse(self.save_called)
self.bot.run()
self.assertEqual(self.page.text,
'Bar\nBaz\n[[Main Page|Label]]\n')
- self.assertTrue(self.save_called)
def test_replace_target(self):
"""Test replacing just target page."""
self._patch_create_callback('t')
- self.assertFalse(self.save_called)
self.bot.run()
self.assertEqual(self.page.text,
'[[Main Page#Foo|Bar]]\n'
'[[Main Page|Baz]]\n'
'[[Main Page|Label]]\n')
- self.assertTrue(self.save_called)
def test_replace_all(self):
"""Test replacing target and label."""
self._patch_create_callback('l')
- self.assertFalse(self.save_called)
self.bot.run()
self.assertEqual(self.page.text,
'[[Main Page#Foo|Main Page]]\n'
'[[Main Page]]\n'
'[[Main Page|Label]]\n')
- self.assertTrue(self.save_called)
if __name__ == '__main__':
--
To view, visit https://gerrit.wikimedia.org/r/218002
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Iaec972f813f2470d1f2e51fde8d59b29d929925c
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <[email protected]>
Gerrit-Reviewer: John Vandenberg <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Merlijn van Deen <[email protected]>
Gerrit-Reviewer: XZise <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
Pywikibot-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/pywikibot-commits