繁体   English   中英

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

[英]How to test while-loop (once) with nosetest (Python 2.7)

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

我在解决它的步骤中解决了问题(我认为):

功能1:

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的时间。 我不明白为什么我没有得到错误 - 或“测试失败”-messages但只是一个“确定”。

除此之外,您可以指出错误的语法和其他可以改进的事情(我真的很感激,如果你这样做的话),我的问题是:

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

所以,这里的问题是你第二次在test中调用inp_3,同时用Mock(return_value="foo") raw_input。 你的inp_3函数运行无限循环( while True ),你不会以任何方式打断它,除非是if s == '1'条件。 因此,对于Mock(return_value="foo") ,该条件永远不会满足,并且循环继续运行,直到您使用外部方式(在您的示例中为Ctrl + C)中断它。 如果它是故意行为,那么如何限制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的书“学习Python”。 它极大地解释了python的基础知识。

更新

我找不到一种方法来模拟python的True(或内置的 .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技巧,比如生成器,“__”方法等。所以要小心使用它。

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

提醒我无限循环是不好的,这一点很重要。 所以,非常感谢你,对于简短的例子,如何让它变得更好。 我会尽可能地做到这一点。

但是,在实际程序中,无限循环是我这次想要的方式。 这里的代码只是简化的问题。 我非常感谢您对修改后的“真实功能”的想法。 我从来没有想过这个,因此我学会了一种新的“方法”来解决编程问题:)。 这次仍然不是我想做的方式,但这是我需要用现有方法解决问题的重要线索。 我第二次调用相同的方法时,我从未考虑过返回不同的值。 它是如此简单和辉煌,令我惊讶:)。

模拟模块具有一些功能,允许每次调用模拟方法时返回不同的值 - 副作用

side_effect也可以设置为可迭代的。 [当]你的模拟将被多次调用,并且你希望每个调用返回一个不同的值。 当你将side_effect设置为iterable时,每次调用mock都会返回iterable中的下一个值:

while循环有一个“退出”(这是它的正确用语吗?)。 它只需要'1'作为输入。 我将用它来退出循环。

def test_inp_3():
    # Test if input is correct
    __builtin__.raw_input = Mock(return_value="1")
    assert_equal(inp_1(), '1')

    # Test if output is correct if input is correct two times.
    # The third time the input is corrct to exit the loop.
    __builtin__.raw_input = Mock(side_effect=['foo', 'bar', '1'])
    out = StringIO()
    sys.stdout = out
    inp_3()
    output = out.getvalue().strip()

    # Make sure to compare as many times as the loop 
    # is "used".
    assert_equal(output, 'wrong\nwrong')

现在测试运行并返回“ok”或错误,例如,如果第一个输入已经退出循环。

再次感谢你的帮助。 这让我的一天:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM