作者:Moshe Zadka
译者:Xingyu.Wang
关于 Ruby 社区的一些事情一直让我印象深刻,其中两个例子是对测试的承诺和对易于上手的强调。这两方面最好的例子是 ,在这里你可以通过修复测试来学习 Ruby。
要是我们能把这些神奇的工具也用于 Python,我们应该可以做得更好。是的,使用 、,再加上一点类似于胶带的粘合代码,我们可以做出一个包括教学、可工作的代码和需要修复的代码的教程。
首先,需要一些胶布。通常,你会使用一些漂亮的命令行测试器来做测试,比如 或 。通常,你甚至不会直接运行它。你使用像 或 这样的工具来运行它。然而,对于 Jupyter 来说,你需要写一小段粘合代码,可以直接在其中运行测试。
幸运的是,这个代码又短又简单:
importunittest
defrun_test(klass):
suite=unittest.TestLoader().loadTestsFromTestCase(klass)
unittest.TextTestRunner(verbosity=2).run(suite)
returnklass
现在,装备已经就绪,可以进行第一次练习了。
在教学中,从一个简单的练习开始,建立信心总是一个好主意。
那么,让我们来修复一个非常简单的测试:
@run_test
classTestNumbers(unittest.TestCase):
deftest_equality(self):
expected_value=3只改这一行
self.assertEqual(1+1,expected_value)
test_equality(__main__.TestNumbers)…FAIL
======================================================================
FAIL:test_equality(__main__.TestNumbers)
———————————————————————-
Traceback(most recent calllast):
File“
“
,line6,intest_equalityself.assertEqual(1+1,expected_value)
AssertionError:2!=3
———————————————————————-
Ran1testin0.002s
FAILED(failures=1)
只改这一行 对学生来说是一个有用的标记。它准确地表明了需要修改的内容。否则,学生可以通过将第一行改为return来修复测试。
在这种情况下,修复很容易:
@run_test
classTestNumbers(unittest.TestCase):
deftest_equality(self):
expected_value=2修复后的代码行
self.assertEqual(1+1,expected_value)
test_equality(__main__.TestNumbers)…ok
———————————————————————-
Ran1testin0.002s
OK
然而,很快,unittest库的原生断言将被证明是不够的。在pytest中,通过重写assert中的字节码来解决这个问题,使其具有神奇的属性和各种启发式方法。但这在 Jupyter notebook 中就不容易实现了。是时候挖出一个好的断言库了:PyHamcrest。
fromhamcrestimport*
@run_test
classTestList(unittest.TestCase):
deftest_equality(self):
things=[1,
5,只改这一行
3]
assert_that(things,has_items(1,2,3))
test_equality(__main__.TestList)…FAIL
======================================================================
FAIL:test_equality(__main__.TestList)
———————————————————————-
Traceback(most recent calllast):
File“
“
,line8,intest_equalityassert_that(things,has_items(1,2,3))
AssertionError:
Expected:(a sequence containing1>anda sequence containing2>anda sequence containing3>)
but:a sequence containing2>was1,5,3]>
———————————————————————-
Ran1testin0.004s
FAILED(failures=1)
PyHamcrest 不仅擅长灵活的断言,它还擅长清晰的错误信息。正因为如此,问题就显而易见了。[1, 5, 3]不包含2,而且看起来很丑:
@run_test
classTestList(unittest.TestCase):
deftest_equality(self):
things=[1,
2,改完的行
3]
assert_that(things,has_items(1,2,3))
test_equality(__main__.TestList)…ok
———————————————————————-
Ran1testin0.001s
OK
使用 Jupyter、PyHamcrest 和一点测试的粘合代码,你可以教授任何适用于单元测试的 Python 主题。
例如,下面可以帮助展示 Python 从字符串中去掉空白的不同方法之间的差异。
source_string=” hello world “
@run_test
classTestList(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)…ok
test_end_strip(__main__.TestList)…FAIL
test_start_strip(__main__.TestList)…FAIL
======================================================================
FAIL:test_end_strip(__main__.TestList)
———————————————————————-
Traceback(most recent calllast):
File“
“
,line19,intest_end_stripassert_that(result,
AssertionError:
Expected:(a string startingwithhelloanda string endingwithworld)
but:a string endingwithworldwashello world
======================================================================
FAIL:test_start_strip(__main__.TestList)
———————————————————————-
Traceback(most recent calllast):
File“
“
,line14,intest_start_stripassert_that(result,
AssertionError:
Expected:(a string startingwithhelloanda string endingwithworld)
but:a string startingwithhellowashello world
———————————————————————-
Ran3testsin0.006s
FAILED(failures=2)
理想情况下,学生们会意识到.lstrip()和.rstrip()这两个方法可以满足他们的需要。但如果他们不这样做,而是试图到处使用.strip()的话:
source_string=” hello world “
@run_test
classTestList(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()改完的行
assert_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)…ok
test_end_strip(__main__.TestList)…FAIL
test_start_strip(__main__.TestList)…FAIL
======================================================================
FAIL:test_end_strip(__main__.TestList)
———————————————————————-
Traceback(most recent calllast):
File“
“
,line19,intest_end_stripassert_that(result,
AssertionError:
Expected:(a string startingwithhelloanda string endingwithworld)
but:a string startingwithhellowashello world
======================================================================
FAIL:test_start_strip(__main__.TestList)
———————————————————————-
Traceback(most recent calllast):
File“
“
,line14,intest_start_stripassert_that(result,
AssertionError:
Expected:(a string startingwithhelloanda string endingwithworld)
but:a string endingwithworldwashello world
———————————————————————-
Ran3testsin0.007s
FAILED(failures=2)
他们会得到一个不同的错误信息,显示去除了过多的空白:
source_string=” hello world “
@run_test
classTestList(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()Fixedthisline
assert_that(result,
all_of(starts_with(“hello”),ends_with(“world “)))
deftest_end_strip(self):
result=source_string.rstrip()Fixedthisline
assert_that(result,
all_of(starts_with(” hello”),ends_with(“world”)))
test_complete_strip(__main__.TestList)…ok
test_end_strip(__main__.TestList)…ok
test_start_strip(__main__.TestList)…ok
———————————————————————-
Ran3testsin0.005s
OK
在一个比较真实的教程中,会有更多的例子和更多的解释。这种使用 Jupyter Notebook 的技巧,有的例子可以用,有的例子需要修正,可以用于实时教学,可以用于视频课,甚至,可以用更多的其它零散用途,让学生自己完成一个教程。
现在就去分享你的知识吧!
via:
作者: 选题: 译者: 校对:
声明:本文部分素材转载自互联网,如有侵权立即删除 。
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别
丞旭猿论坛
暂无评论内容