jenkins-bot has submitted this change and it was merged.
Change subject: [FEAT] bot tests: Tests for the Bot classes
......................................................................
[FEAT] bot tests: Tests for the Bot classes
This does a few read only tests to verify that the classes iterate correctly
over the pages.
Change-Id: I31f5321e1f11b1c924ee97296e0cd81bd6293d5f
---
A tests/bot_tests.py
1 file changed, 232 insertions(+), 0 deletions(-)
Approvals:
John Vandenberg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/tests/bot_tests.py b/tests/bot_tests.py
new file mode 100644
index 0000000..c8b8316
--- /dev/null
+++ b/tests/bot_tests.py
@@ -0,0 +1,232 @@
+# -*- coding: utf-8 -*-
+"""Bot tests."""
+#
+# (C) Pywikibot team, 2015
+#
+# Distributed under the terms of the MIT license.
+#
+from __future__ import unicode_literals
+
+__version__ = '$Id$'
+#
+import sys
+
+import pywikibot
+import pywikibot.bot
+
+from tests.aspects import unittest, DefaultSiteTestCase, SiteAttributeTestCase
+
+
+class TestBotTreatExit(object):
+
+ """Mixin to provide handling for treat and exit."""
+
+ def _treat(self, pages, post_treat=None):
+ """
+ Get tests which are executed on each treat.
+
+ It uses pages as an iterator and compares the page given to the page
+ returned by pages iterator. It checks that the bot's _site and site
+ attributes are set to the page's site. If _treat_site is set with a
Site
+ it compares it to that one too.
+
+ Afterwards it calls post_treat so it's possible to do additional
checks.
+ """
+ def treat(page):
+ self.assertEqual(page, next(self._page_iter))
+ self.assertIsNotNone(self.bot._site)
+ self.assertEqual(self.bot.site, self.bot._site)
+ if self._treat_site:
+ self.assertEqual(self.bot._site, self._treat_site)
+ self.assertEqual(page.site, self.bot.site)
+ if post_treat:
+ post_treat(page)
+ self._page_iter = iter(pages)
+ return treat
+
+ def _treat_page(self, pages=True, post_treat=None):
+ """
+ Adjust to CurrentPageBot signature.
+
+ It uses almost the same logic as _treat but returns a wrapper function
+ which itself calls the function returned by _treat.
+
+ The pages may be set to True which sill use _treat_generator as the
+ source for the pages.
+ """
+ def treat_page():
+ treat(self.bot.current_page)
+
+ if pages is True:
+ pages = self._treat_generator()
+ treat = self._treat(pages, post_treat)
+ return treat_page
+
+ def _exit(self, treated, written=0, exception=None):
+ """Get tests which are executed on exit."""
+ def exit():
+ exc = sys.exc_info()[0]
+ if exc is AssertionError:
+ # When an AssertionError happened we shouldn't do these
+ # assertions as they are invalid anyway and hide the actual
+ # failed assertion
+ return
+ self.assertEqual(self.bot._treat_counter, treated)
+ self.assertEqual(self.bot._save_counter, written)
+ if exception:
+ self.assertIs(exc, exception)
+ else:
+ self.assertIsNone(exc)
+ self.assertRaises(StopIteration, next, self._page_iter)
+ return exit
+
+
+class TestDrySiteBot(TestBotTreatExit, SiteAttributeTestCase):
+
+ """Tests for the BaseBot subclasses."""
+
+ dry = True
+
+ sites = {
+ 'de': {
+ 'family': 'wikipedia',
+ 'code': 'de'
+ },
+ 'en': {
+ 'family': 'wikipedia',
+ 'code': 'en'
+ }
+ }
+
+ def _generator(self):
+ """Generic generator."""
+ yield pywikibot.Page(self.de, 'Page 1')
+ yield pywikibot.Page(self.en, 'Page 2')
+ yield pywikibot.Page(self.de, 'Page 3')
+ yield pywikibot.Page(self.en, 'Page 4')
+
+ def test_Bot(self):
+ """Test normal Bot class."""
+ # Assert no specific site
+ self._treat_site = False
+ self.bot = pywikibot.bot.Bot(generator=self._generator())
+ self.bot.treat = self._treat(self._generator())
+ self.bot.exit = self._exit(4)
+ self.bot.run()
+
+ def test_CurrentPageBot(self):
+ """Test normal Bot class."""
+ def post_treat(page):
+ self.assertIs(self.bot.current_page, page)
+ # Assert no specific site
+ self._treat_site = False
+ self.bot = pywikibot.bot.CurrentPageBot(generator=self._generator())
+ self.bot.treat_page = self._treat_page(self._generator(), post_treat)
+ self.bot.exit = self._exit(4)
+ self.bot.run()
+
+ def test_Bot_ValueError(self):
+ """Test normal Bot class with a ValueError in treat."""
+ def post_treat(page):
+ if page.title() == 'Page 3':
+ raise ValueError('Whatever')
+
+ self._treat_site = False
+ self.bot = pywikibot.bot.Bot(generator=self._generator())
+ self.bot.treat = self._treat([pywikibot.Page(self.de, 'Page 1'),
+ pywikibot.Page(self.en, 'Page 2'),
+ pywikibot.Page(self.de, 'Page 3')],
+ post_treat)
+ self.bot.exit = self._exit(2, exception=ValueError)
+ self.assertRaises(ValueError, self.bot.run)
+
+ def test_Bot_KeyboardInterrupt(self):
+ """Test normal Bot class with a KeyboardInterrupt in treat."""
+ def post_treat(page):
+ if page.title() == 'Page 3':
+ raise KeyboardInterrupt('Whatever')
+
+ self._treat_site = False
+ self.bot = pywikibot.bot.Bot(generator=self._generator())
+ self.bot.treat = self._treat([pywikibot.Page(self.de, 'Page 1'),
+ pywikibot.Page(self.en, 'Page 2'),
+ pywikibot.Page(self.de, 'Page 3')],
+ post_treat)
+
+ # TODO: sys.exc_info is empty in Python 3
+ if sys.version_info[0] > 2:
+ exc = None
+ else:
+ exc = KeyboardInterrupt
+ self.bot.exit = self._exit(2, exception=exc)
+ self.bot.run()
+
+
+# TODO: This could be written as dry tests probably by faking the important
+# properties
+class LiveBotTestCase(TestBotTreatExit, DefaultSiteTestCase):
+
+ """Test bot classes which need to check the Page object live."""
+
+ def _treat_generator(self):
+ """Yield the current page until it's None."""
+ while self._current_page:
+ yield self._current_page
+
+ def _missing_generator(self):
+ """Yield pages and the last one does not exist."""
+ self._count = 1
+ self._current_page = list(self.site.allpages(total=1))[0]
+ yield self._current_page
+ while self._current_page.exists():
+ self._count += 1
+ self._current_page = pywikibot.Page(
+ self.site, self._current_page.title() + 'X')
+ yield self._current_page
+ self._current_page = None
+
+ def _exit(self, treated=None, written=0, exception=None):
+ """Set the number of treated pages to _count."""
+ def exit():
+ t = self._count if treated is None else treated
+ super(LiveBotTestCase, self)._exit(t, written, exception)()
+ return exit
+
+ def test_ExistingPageBot(self):
+ """Test ExistingPageBot class."""
+ def post_treat(page):
+ """Verify the page exists."""
+ self.assertTrue(page.exists())
+
+ self._treat_site = False
+ self.bot = pywikibot.bot.ExistingPageBot(
+ generator=self._missing_generator())
+ self.bot.treat_page = self._treat_page(post_treat=post_treat)
+ self.bot.exit = self._exit()
+ self.bot.run()
+
+ def test_CreatingPageBot(self):
+ """Test CreatingPageBot class."""
+ # This doesn't verify much (e.g. it could yield the first existing
page)
+ # but the assertion in post_treat should verify that the page is valid
+ def treat_generator():
+ """Yield just one current page (the last one)."""
+ yield self._current_page
+
+ def post_treat(page):
+ """Verify the page is missing."""
+ self.assertFalse(page.exists())
+
+ self._treat_site = False
+ self.bot = pywikibot.bot.CreatingPageBot(
+ generator=self._missing_generator())
+ self.bot.treat_page = self._treat_page(treat_generator(), post_treat)
+ self.bot.exit = self._exit()
+ self.bot.run()
+
+
+if __name__ == '__main__':
+ try:
+ unittest.main()
+ except SystemExit:
+ pass
--
To view, visit https://gerrit.wikimedia.org/r/218328
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I31f5321e1f11b1c924ee97296e0cd81bd6293d5f
Gerrit-PatchSet: 2
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: jenkins-bot <>
_______________________________________________
Pywikibot-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/pywikibot-commits