使用Jupyter、PyHamcrest和一些将它们捆绑在一起的测试代码,您可以教授任何适合单元测试的Python。Ruby社区的一些事情总是让我印象深刻,两个例子是对测试的承诺和对易用性的强调。两者最好的例子是RubyKoans,您可以在其中通过修复测试来学习Ruby。如果我们能够将这些神奇的工具引入Python,我们应该能够做得更好。是的,使用JupyterNotebook、PyHamcrest和一点胶带将代码粘合在一起,我们可以制作一个教程,其中包括教学、工作代码和需要修复的代码。首先,需要一些“胶带”。通常,您会使用一些不错的命令行测试器来进行测试,例如pytest或virtual。通常,您甚至不会直接运行它。您可以使用tox或nox等工具来运行它。但是,使用Jupyter,您需要编写一小段胶水代码,您可以在其中直接运行测试。幸运的是,这段代码简短而简单:importunittestdefrun_test(klass):suite=unittest.TestLoader().loadTestsFromTestCase(klass)unittest.TextTestRunner(verbosity=2).run(suite)returnklass现在,装备准备好了,可以进行第一次练习。在教学中,从简单的练习开始建立信心总是一个好主意。所以,让我们修复一个非常简单的测试:@run_testclassTestNumbers(unittest.TestCase):deftest_equality(self):expected_value=3#只需更改这一行self.assertEqual(1+1,expected_value)test_equality(__main__.TestNumbers)...失败=========================================================================失败:test_equality(__main__.TestNumbers)-----------------------------------------------------------------回溯(最近调用最后):文件“”,第6行,在test_equalityself.assertEqual(1+1,expected_value)AssertionError:2!=3-----------------------------------------------------------------在0.002秒内进行1次测试失败(失败=1)“仅更改此行”对学生来说是一个有用的标志。它准确地显示了需要修改的内容。否则,学生可以通过将第一行更改为return来修复测试。在这种情况下修复很容易:@run_testclassTestNumbers(unittest.TestCase):deftest_equality(self):expected_value=2#固定行self.assertEqual(1+1,expected_value)test_equality(__main__.TestNumbers)..。好的----------------------------------------------在0.002秒内运行1个测试OK很快,unittest库的本机断言将被证明是不够的。在pytest中,这个问题是通过重写assert中的字节码来解决的,使其具有魔法属性和各种启发式。但这在JupyterNotebook中并不容易实现。是时候挖掘一个好的断言库了:PyHamcrest。fromhamcrestimport*@run_testclassTestList(unittest.TestCase):deftest_equality(self):things=[1,5,#只改这一步3]assert_that(things,has_items(1,2,3))test_equality(__main__.测试列表)...失败======================================================================失败:test_equality(__main__.TestList)------------------------------------------------------------------回溯(最后一次调用):文件“”,第8行,在test_equalityassert_that(things,has_items(1,2,3))AssertionError:Expected:(asequence包含<1>和包含<2>的序列和包含<3>的序列)但是:包含<2>的序列是<[1,5,3]>-----------------------------------------------------------------在0.004秒内运行1次测试失败(失败=1)PyHamcrest不仅擅长灵活的断言,还擅长清晰的错误信息,正因为如此,问题就很明显了。[1,5,3]不包含2,而且看起来很丑:@run_testclassTestList(unittest.TestCase):deftest_equality(self):things=[1,2,#modifiedline3]assert_that(things,has_items(1,2,3))test_equality(__main__.TestList)...好吧-------------------------------------------------------------------使用Jupyter、PyHamcrest在0.001秒内完成1次测试用于测试的胶水代码,您可以教授任何适用于单元测试的Python主题。例如,以下内容可以帮助显示Python从字符串中去除空格的不同方法之间的差异。source_string="helloworld"@run_testclassTestList(unittest.TestCase):#这是一个赠品:它有效!deftest_complete_strip(self):result=source_string.strip()assert_that(result,all_of(starts_with("hello"),ends_with("world")))deftest_start_strip(self):result=source_string#只改变这一行assert_that(result,all_of(starts_with("hello"),ends_with("world")))deftest_end_strip(self):result=source_string#只改变这一行assert_that(result,all_of(starts_with("hello"),ends_with("world")))test_complete_strip(__main__.TestList)...oktest_end_strip(__main__.TestList)...失败test_start_strip(__main__.TestList)...失败=========================================================================失败:test_end_strip(__main__.TestList)----------------------------------------------------------------追溯(最近的通话最后):文件“”,第19行,在test_end_stripassert_that(结果,AssertionError:预期:(以“hello”开头的字符串和以“world”结尾的字符串)但是:一个字符串以'world'结尾的是'helloworld'======================================================================失败:test_start_strip(__main__.TestList)----------------------------------------------------------------回溯(最近调用最后):文件“”,第14行,在test_start_stripassert_that(result,AssertionError:Expected:(astringwithstartingwith'hello'和以'world'结尾的字符串)但是:以'hello'开头的字符串是'helloworld'-------------------------------------------------------------------在0.006秒内进行3次测试失败(失败=2)理想情况下,学生会意识到这两种方法.lstrip()和.rstrip()会做他们需要的但如果他们不这样做并尝试在任何地方使用.strip():source_string="helloworld"@run_testclassTestList(unittest.TestCase):#这是一个赠品:它有效!deftest_complete_strip(self):result=source_string.strip()assert_that(result,all_of(starts_with("hello"),ends_with("world")))deftest_start_strip(self):result=source_string.strip()#完成了lineassert_that(result,all_of(starts_with("hello"),ends_with("world")))deftest_end_strip(self):result=source_string.strip()#修改后的行assert_that(result,all_of(starts_with("hello"),ends_with("world")))test_complete_strip(__main__.TestList)...oktest_end_strip(__main__.TestList)...失败test_start_strip(__main__.TestList)...失败=======================================================================失败:test_end_strip(__ma在__.TestList)------------------------------------------------------------------追溯(最近调用最后):文件“”,第19行,在test_end_stripassert_that(result,AssertionError:Expected:(astringwithstartingwith'hello'andastringendingwith'world')但是:以'hello'开头的字符串是'helloworld'====================================================================失败:test_start_strip(__main__.TestList)------------------------------------------------------------------回溯(最近调用最后):文件“",line14,intest_start_stripassert_that(result,AssertionError:Expected:(astringwithstartingwith'hello'andastringendingwith'world')but:astringendingwith'world'is'hello世界'------------------------------------------------------在0.007秒内进行3次测试失败(failures=2)他们会收到一条不同的错误消息,显示删除了太多空格:source_string="helloworld"@run_testclassTestList(unittest.TestCase):#这是一个赠品:它有效!deftest_complete_strip(self):result=source_string.strip()assert_that(result,all_of(starts_with("hello"),ends_with("world")))deftest_start_strip(self):result=source_string.lstrip()#修复了这个lineassert_that(result,all_of(starts_with("hello"),ends_with("world")))deftest_end_strip(self):result=source_string.rstrip()#修复了这一行assert_that(result,all_of(starts_with("hello"),ends_with("world")))test_complete_strip(__main__.TestList)...好的test_end_strip(__main__.TestList)...好的test_start_strip(__main__.TestList)...好的------------------------------------------------在0.005秒内跑了3次测试OK在更现实的教程中,会有更多的例子和更多的解释这种使用JupyterNotebook的技巧,一些例子可以用,一些例子需要批改,可以用于实时教学,可以用于视频课,更多的是其他零散的用途,让学生自己完成一个教程。