python - 如何使用 nosetest (Python 2.7) 测试 while 循环(一次)

标签 python python-2.7 nose

我对这整个“编程事物”还很陌生,但在 34 岁时,我认为我想学习基础知识。 不幸的是,我不认识任何 python 程序员。我学习编程是出于个人兴趣(而且越来越多是为了乐趣),但我的“社交栖息地”不是“程序员漫游的地方”;)。 我几乎完成了 Zed Shaws 的“艰难地学习 Python”,这是我第一次找不到问题的解决方案。在过去的两天里,当我反复改写(并搜索)我的问题时,我什至没有偶然发现有用的提示。 所以stackoverflow似乎是正确的地方。 顺便说一句:我也经常缺乏正确的词汇,所以请不要犹豫纠正我:)。这可能是我找不到答案的原因之一。 我使用 Python 2.7 和 nosetests。

我在解决问题的步骤中(我认为)在多大程度上解决了这个问题:

函数一:

def inp_1():
    s = raw_input(">>> ")
    return s

所有测试都导入以下内容以执行以下操作:

from nose.tools import *
import sys
from StringIO import StringIO
from mock import *
import __builtin__
# and of course the module with the functions

这是 inp_1 的测试:

import __builtin__
from mock import *

def test_inp_1():
    __builtin__.raw_input = Mock(return_value="foo")
    assert_equal(inp_1(), 'foo')

这个功能/测试没问题。

非常相似的是下面的函数2:

def inp_2():
    s = raw_input(">>> ")
    if s == '1':
        return s
    else:
        print "wrong"

测试:

def test_inp_2():
    __builtin__.raw_input = Mock(return_value="1")
    assert_equal(inp_1(), '1')

    __builtin__.raw_input = Mock(return_value="foo")
    out = StringIO()
    sys.stdout = out
    inp_1()
    output = out.getvalue().strip()
    assert_equal(output, 'wrong')

这个功能/测试也是可以的。

当我使用上述所有内容时,请不要假设我真的知道“幕后”发生了什么。我有一些外行解释这是如何运作的,以及为什么我得到我想要的结果,但我也觉得这些解释可能并不完全正确。这不是我第一次这么想……学多了作品就不一样了。特别是所有带有“__”的东西都让我感到困惑,我不敢使用它,因为我真的不明白发生了什么。无论如何,现在我“只是”想添加一个 while 循环来请求输入,直到输入正确为止:

def inp_3():
    while True:
        s = raw_input(">>> ")
        if s == '1':
            return s
        else:
            print "wrong"

我认为对 inp_3 的测试与对 inp_2 的测试相同。至少我没有收到错误消息。但输出如下:

$ nosetests
......

     # <- Here I press ENTER to provoke a reaction
     # Nothing is happening though.

^C   # <- Keyboard interrupt (is this the correct word for it?)
----------------------------------------------------------------------
Ran 7 tests in 5.464s

OK
$ 

其他 7 个测试是……。否则(好吧)。 inp_3 的测试将是测试 nr。 8. 时间就是我按下 CTRL-C 之前耗时。 我不明白为什么我没有收到错误消息或“测试失败”消息,而是收到“确定”消息。

所以除了您可能能够指出错误的语法和其他可以改进的地方(如果您愿意这样做,我真的很感激),我的问题是:

如何使用 nosetest 测试和中止 while 循环?

最佳答案

因此,这里的问题是当您第二次在测试中调用 inp_3 时,同时使用 Mock(return_value="foo") 模拟 raw_input。您的 inp_3 函数运行无限循环 (while True) ,并且除了 if s == '1' 条件外,您不会以任何方式中断它。因此,使用 Mock(return_value="foo") 永远不会满足该条件,并且您的循环会一直运行,直到您用外部方式(在您的示例中为 Ctrl + C)中断它。如果是故意行为,则 How to limit execution time of a function call in Python将帮助您限制 inp_3 在测试中的执行时间。但是,在您的示例中的输入情况下,开发人员通常会限制用户的输入尝试次数。您可以使用变量来计算尝试次数,当它达到最大值时,应该停止循环。

def inp_3():
    max_attempts = 5
    attempts = 0
    while True:
        s = raw_input(">>> ")
        attempts += 1 # this is equal to "attempts = attempts + 1"
        if s == '1':
            return s
        else:
            print "wrong"
            if attempts == max_attempts:
                print "Max attempts used, stopping."
                break # this is used to stop loop execution
                # and go to next instruction after loop block

    print "Stopped."

另外,要学习 Python,我可以推荐 Mark Lutz 的书“Learning Python”。它很好地解释了 python 的基础知识。

更新:

我找不到一种方法来模拟 python 的 True(或 builtin.True)(是的,这听起来有点疯狂),看起来 python 没有(也不会) ) 请允许我这样做。但是,要准确实现您想要的效果,即运行一次无限循环,您可以使用一些技巧。

定义一个返回True的函数

def true_func():
    return True

,在while循环中使用

while true_func():

然后用这样的逻辑在测试中模拟它:

def true_once():
    yield True
    yield False


class MockTrueFunc(object):
    def __init__(self):
        self.gen = true_once()

    def __call__(self):
        return self.gen.next()

然后在测试中:

true_func = MockTrueFunc()

这样你的循环将只运行一次。但是,此构造使用了一些高级 Python 技巧,例如生成器、“__”方法等。因此请谨慎使用。

但无论如何,无限循环通常被认为是糟糕的设计解决方案。最好不要习惯它:)。

关于python - 如何使用 nosetest (Python 2.7) 测试 while 循环(一次),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27191543/

相关文章:

python - 如何为 Python 安装手动传递 bzip2 安装源?

python - 在脚本中使用 Python 中的 nose 时覆盖现有配置

javascript - 从 python 中的动态 mpld3 图中检索数据

python - 只在 Pandas 组的字典中保留没有无值的键

python - tensorflow 值错误: Too many vaues to unpack (expected 2)

python - gae-sessions 和 nose 的错误

Numpy 安装 Mac Osx Python

python - 为什么使类可迭代会产生此输出?

python - 版本名称 'cp27' 或 'cp35' 在 Python 中是什么意思?

python - 根据某些条件分配 pandas DataFrame 单元格的内容而不使用循环