为什么这个 doctest 在 Pycharm 中传递,而不是在命令行中传递?
Why does this doctest pass in Pycharm, but not on the command line?
我在 Python 3.9 doctests 中有一个非常奇怪的单元测试失败。通常我必须清理我的问题,但这是相当低级的代码,所以我可以 post 在这里完整地解决它。
我可以 运行 在 Pycharm 中进行这个 doctest 没有问题。当我在命令行上 运行 它时,我得到了一个毫无意义的失败。任何帮助将不胜感激。
quadratic_solver.py
import math
import numpy as np
import doctest
def solve(
a: float,
b: float,
c: float):
"""
:return: the roots of the quadratic arranged in a 0-2 floating point value-long array
>>> roots = solve(2., -1., 100.) # noRoots
>>> len(roots)
0
>>> roots = solve(1., 2., 1.) # oneRoot
>>> len(roots)
1
>>> round(roots[0], 9)
-1.0
>>> roots = solve(1., 4., 1.) # twoRoots_1
>>> len(roots)
2
>>> round(roots[0], 9)
-3.732050808
>>> round(roots[1], 9)
-0.267949192
>>> roots = solve(-9., 61., 19.) # twoRoots_2
>>> len(roots)
2
>>> round(roots[0], 9)
-0.298343001
>>> round(roots[1], 9)
7.076120779
"""
# https://math.stackexchange.com/questions/866331/numerically-stable-algorithm-for-solving-the-quadratic-equation-when-a-is-very
desc = b**2 - 4. * a * c
if desc < 0.:
# no roots
return np.array([])
elif desc == 0.:
# one root
root = -b / (2. * a)
return np.array([root])
else:
d = math.sqrt(b**2 - 4. * a * c)
root1 = (-b + d) / (2. * a)
root2 = (-b - d) / (2. * a)
if root1 < root2:
return np.array([root1, root2])
else:
return np.array([root2, root1])
doctest.testmod()
运行宁python -m doctest $PATH_TO_FILE$/quadratic_solver.py
时的错误信息:
**********************************************************************
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1820, in __main__.DebugRunner
Failed example:
runner.run(test)
Expected:
Traceback (most recent call last):
...
doctest.UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
Got:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1336, in __run
exec(compile(example.source, filename, "single",
File "<doctest __main__.DebugRunner[15]>", line 1, in <module>
runner.run(test)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1844, in run
r = DocTestRunner.run(self, test, compileflags, out, False)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1483, in run
return self.__run(test, compileflags, out)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1388, in __run
self.report_unexpected_exception(out, test, example,
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1850, in report_unexpected_exception
raise UnexpectedException(test, example, exc_info)
UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
**********************************************************************
这里的问题是 doctest.testmod()
.
行
PyCharm 只是检测到 Python 模块中有 doctests,并且 运行 使用它自己的 doctest 运行ner 对它们进行了测试,所以它只是忽略了那一行.
如果您从命令行调用 docster,它的作用基本相同:它检测所有的 doctests 并 运行s 它们,但是 此外它还尝试doctest doctest 执行行。如果你使用详细输出,你可以看到这个:
python -m doctest -v $PATH_TO_FILE$/quadratic_solver.py
这表明所有的 doctests 都是正确的 运行,然后执行 doctest
中的测试。那里 doctest
中的 类 之一(即 DebugRunner
)本身有一个失败的 doctest(不确定这是一个错误,还是只是不打算成为 运行 这个方式)。
这样做的原因是,如果通过库(使用 if __name__ == "__main__"
)调用测试运行ner 代码,在这种情况下是从 docster 调用的,那么您不会保护它不被执行。
所以要解决这个问题,您有两种可能性:
- 删除调用 doctests 的行;这将使它在命令行上与 doctest 一起工作
- 使用:
if __name__ == "__main__":
doctest.testmod()
这将使它与通过 doctest 的调用一起工作:
python -m doctest $PATH_TO_FILE$/quadratic_solver.py
以及模块中刚刚执行 doctest 行的调用:
python $PATH_TO_FILE$/quadratic_solver.py
请注意,第二个变体也适用于您当前的代码,但这也意味着每次您从其他地方导入库时都会执行 doctests,这是您肯定不希望的。
我在 Python 3.9 doctests 中有一个非常奇怪的单元测试失败。通常我必须清理我的问题,但这是相当低级的代码,所以我可以 post 在这里完整地解决它。
我可以 运行 在 Pycharm 中进行这个 doctest 没有问题。当我在命令行上 运行 它时,我得到了一个毫无意义的失败。任何帮助将不胜感激。
quadratic_solver.py
import math
import numpy as np
import doctest
def solve(
a: float,
b: float,
c: float):
"""
:return: the roots of the quadratic arranged in a 0-2 floating point value-long array
>>> roots = solve(2., -1., 100.) # noRoots
>>> len(roots)
0
>>> roots = solve(1., 2., 1.) # oneRoot
>>> len(roots)
1
>>> round(roots[0], 9)
-1.0
>>> roots = solve(1., 4., 1.) # twoRoots_1
>>> len(roots)
2
>>> round(roots[0], 9)
-3.732050808
>>> round(roots[1], 9)
-0.267949192
>>> roots = solve(-9., 61., 19.) # twoRoots_2
>>> len(roots)
2
>>> round(roots[0], 9)
-0.298343001
>>> round(roots[1], 9)
7.076120779
"""
# https://math.stackexchange.com/questions/866331/numerically-stable-algorithm-for-solving-the-quadratic-equation-when-a-is-very
desc = b**2 - 4. * a * c
if desc < 0.:
# no roots
return np.array([])
elif desc == 0.:
# one root
root = -b / (2. * a)
return np.array([root])
else:
d = math.sqrt(b**2 - 4. * a * c)
root1 = (-b + d) / (2. * a)
root2 = (-b - d) / (2. * a)
if root1 < root2:
return np.array([root1, root2])
else:
return np.array([root2, root1])
doctest.testmod()
运行宁python -m doctest $PATH_TO_FILE$/quadratic_solver.py
时的错误信息:
**********************************************************************
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1820, in __main__.DebugRunner
Failed example:
runner.run(test)
Expected:
Traceback (most recent call last):
...
doctest.UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
Got:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1336, in __run
exec(compile(example.source, filename, "single",
File "<doctest __main__.DebugRunner[15]>", line 1, in <module>
runner.run(test)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1844, in run
r = DocTestRunner.run(self, test, compileflags, out, False)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1483, in run
return self.__run(test, compileflags, out)
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1388, in __run
self.report_unexpected_exception(out, test, example,
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/doctest.py", line 1850, in report_unexpected_exception
raise UnexpectedException(test, example, exc_info)
UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
**********************************************************************
这里的问题是 doctest.testmod()
.
PyCharm 只是检测到 Python 模块中有 doctests,并且 运行 使用它自己的 doctest 运行ner 对它们进行了测试,所以它只是忽略了那一行.
如果您从命令行调用 docster,它的作用基本相同:它检测所有的 doctests 并 运行s 它们,但是 此外它还尝试doctest doctest 执行行。如果你使用详细输出,你可以看到这个:
python -m doctest -v $PATH_TO_FILE$/quadratic_solver.py
这表明所有的 doctests 都是正确的 运行,然后执行 doctest
中的测试。那里 doctest
中的 类 之一(即 DebugRunner
)本身有一个失败的 doctest(不确定这是一个错误,还是只是不打算成为 运行 这个方式)。
这样做的原因是,如果通过库(使用 if __name__ == "__main__"
)调用测试运行ner 代码,在这种情况下是从 docster 调用的,那么您不会保护它不被执行。
所以要解决这个问题,您有两种可能性:
- 删除调用 doctests 的行;这将使它在命令行上与 doctest 一起工作
- 使用:
if __name__ == "__main__":
doctest.testmod()
这将使它与通过 doctest 的调用一起工作:
python -m doctest $PATH_TO_FILE$/quadratic_solver.py
以及模块中刚刚执行 doctest 行的调用:
python $PATH_TO_FILE$/quadratic_solver.py
请注意,第二个变体也适用于您当前的代码,但这也意味着每次您从其他地方导入库时都会执行 doctests,这是您肯定不希望的。