M python 2/runner/runner_tests/test_sensei.py +2 -2
@@ 404,5 404,5 @@ class TestSensei(unittest.TestCase):
def test_filter_all_lessons_will_discover_test_classes_if_none_have_been_discovered_yet(self):
self.sensei.all_lessons = 0
- self.assertTrue(self.sensei.filter_all_lessons() > 10)
- self.assertTrue(self.sensei.all_lessons > 10)
+ self.assertTrue(len(self.sensei.filter_all_lessons()) > 10)
+ self.assertTrue(len(self.sensei.all_lessons) > 10)
M python 2/runner/sensei.py +1 -4
@@ 3,16 3,13 @@
import unittest
import re
+import glob
import helper
from mockable_test_result import MockableTestResult
from runner import path_to_enlightenment
from libs.colorama import init, Fore, Style
-import glob
-
-init()
-
class Sensei(MockableTestResult):
def __init__(self, stream):
M python 3/runner/runner_tests/test_mountain.py +1 -5
@@ 14,12 14,8 @@ class TestMountain(unittest.TestCase):
self.mountain = Mountain()
self.mountain.stream.writeln = Mock()
- def test_it_retrieves_some_koans_tests(self):
- self.mountain.walk_the_path()
- self.assertTrue(self.mountain.tests, "No test suite")
-
def test_it_gets_test_results(self):
self.mountain.lesson.learn = Mock()
self.mountain.walk_the_path()
self.assertTrue(self.mountain.lesson.learn.called)
-
No newline at end of file
+
M python 3/runner/runner_tests/test_sensei.py +36 -0
@@ 10,6 10,7 @@ from libs.mock import *
from runner.sensei import Sensei
from runner.writeln_decorator import WritelnDecorator
from runner.mockable_test_result import MockableTestResult
+from runner import path_to_enlightenment
class AboutParrots:
pass
@@ 86,6 87,9 @@ class TestSensei(unittest.TestCase):
def setUp(self):
self.sensei = Sensei(WritelnDecorator(sys.stdout))
self.sensei.stream.writeln = Mock()
+ path_to_enlightenment.koans = Mock()
+ self.tests = Mock()
+ self.tests.countTestCases = Mock()
def test_that_it_delegates_testing_to_test_cases(self):
MockableTestResult.startTest = Mock()
@@ 229,6 233,15 @@ class TestSensei(unittest.TestCase):
self.sensei.learn()
self.assertTrue(self.sensei.stream.writeln.called)
+ def test_that_end_report_shows_student_progress(self):
+ self.sensei.errorReport = Mock()
+ self.sensei.total_lessons = Mock()
+ self.sensei.total_koans = Mock()
+
+ self.sensei.learn()
+ self.assertTrue(self.sensei.total_lessons.called)
+ self.assertTrue(self.sensei.total_koans.called)
+
def test_that_end_report_shows_the_failure_report(self):
self.sensei.errorReport = Mock()
self.sensei.learn()
@@ 371,3 384,26 @@ class TestSensei(unittest.TestCase):
m = re.search("Beautiful is better than ugly", words)
self.assertTrue(m and m.group(0))
+
+ def test_that_total_lessons_return_7_if_there_are_7_lessons(self):
+ self.sensei.filter_all_lessons = Mock()
+ self.sensei.filter_all_lessons.return_value = [1,2,3,4,5,6,7]
+
+ self.assertEqual(7, self.sensei.total_lessons())
+
+ def test_that_total_lessons_return_0_if_all_lessons_is_none(self):
+ self.sensei.filter_all_lessons = Mock()
+ self.sensei.filter_all_lessons.return_value = None
+
+ self.assertEqual(0, self.sensei.total_lessons())
+
+ def test_total_koans_return_43_if_there_are_43_test_cases(self):
+ self.sensei.tests.countTestCases = Mock()
+ self.sensei.tests.countTestCases.return_value = 43
+
+ self.assertEqual(43, self.sensei.total_koans())
+
+ def test_filter_all_lessons_will_discover_test_classes_if_none_have_been_discovered_yet(self):
+ self.sensei.all_lessons = 0
+ self.assertTrue(len(self.sensei.filter_all_lessons()) > 10)
+ self.assertTrue(len(self.sensei.all_lessons) > 10)
M python 3/runner/sensei.py +35 -3
@@ 3,19 3,23 @@
import unittest
import re
+import glob
from . import helper
from .mockable_test_result import MockableTestResult
+from runner import path_to_enlightenment
from libs.colorama import init, Fore, Style
-
class Sensei(MockableTestResult):
def __init__(self, stream):
unittest.TestResult.__init__(self)
self.stream = stream
self.prevTestClassName = None
+ self.tests = path_to_enlightenment.koans()
self.pass_count = 0
+ self.lesson_pass_count = 0
+ self.all_lessons = None
def startTest(self, test):
MockableTestResult.startTest(self, test)
@@ 26,6 30,8 @@ class Sensei(MockableTestResult):
self.stream.writeln()
self.stream.writeln("{0}{1}Thinking {2}".format(
Fore.RESET, Style.NORMAL, helper.cls_name(test)))
+ if helper.cls_name(test) != 'AboutAsserts':
+ self.lesson_pass_count += 1
def addSuccess(self, test):
if self.passesCount():
@@ 76,6 82,8 @@ class Sensei(MockableTestResult):
self.stream.writeln("")
self.stream.writeln("")
+ self.stream.writeln(self.report_progress())
+ self.stream.writeln("")
self.stream.writeln(self.say_something_zenlike())
if self.failures: return
@@ 102,8 110,8 @@ class Sensei(MockableTestResult):
self.stream.writeln("")
self.stream.writeln("{0}{1}Please meditate on the following code:" \
.format(Fore.RESET, Style.NORMAL))
- self.stream.writeln("{0}{1}{2}".format(Fore.YELLOW, Style.BRIGHT, \
- self.scrapeInterestingStackDump(err)))
+ self.stream.writeln("{0}{1}{2}{3}{4}".format(Fore.YELLOW, Style.BRIGHT, \
+ self.scrapeInterestingStackDump(err), Fore.RESET, Style.NORMAL))
def scrapeAssertionError(self, err):
if not err: return ""
@@ 146,6 154,13 @@ class Sensei(MockableTestResult):
scrape += line + '\n'
return scrape.replace(sep, '\n').strip('\n')
+ def report_progress(self):
+ return ("You are now {0}/{1} lessons and {2}/{3} koans away from " \
+ "reaching enlightenment".format(self.lesson_pass_count,
+ self.total_lessons(),
+ self.pass_count,
+ self.total_koans()))
+
# Hat's tip to Tim Peters for the zen statements from The Zen
# of Python (http://www.python.org/dev/peps/pep-0020/)
#
@@ 210,3 225,20 @@ class Sensei(MockableTestResult):
# Hopefully this will never ever happen!
return "The temple in collapsing! Run!!!"
+
+ def total_lessons(self):
+ all_lessons = self.filter_all_lessons()
+ if all_lessons:
+ return len(all_lessons)
+ else:
+ return 0
+
+ def total_koans(self):
+ return self.tests.countTestCases()
+
+ def filter_all_lessons(self):
+ if not self.all_lessons:
+ self.all_lessons = glob.glob('koans/about*.py')
+ self.all_lessons.remove('koans/about_extra_credit.py')
+
+ return self.all_lessons