python - 在 python 中测试 while 循环

标签 python testing

测试如下方法的最佳方法是什么

class Foo(object):

   is_running = False
   def run(self):
       self.is_running = True
       while self.is_running:
           do_some_work()

对于消费者来说,这是非常标准的代码,在设置 is_running 标志时进行工作。

但这很难测试,因为除非我创建第二个线程将 is_running 更改为 false,否则它将进入循环并且永远不会出来。

是否有任何好的策略可以在不启动单独的线程来运行代码的情况下进行测试?

我还没有看到任何东西,但我想也许模拟库会提供每次读取 is_running 时都可以返回 [True, True, False] 的功能但这是否需要我将 is_running 从成员变量更改为属性或方法?

最佳答案

正如我在评论中提到的,我认为使用线程测试此方法是一种完全可行的方法,并且可能是最好的解决方案。但是,如果您确实想避免线程,可以将 is_running 转换为 property,然后使用 mock.PropertyMock模拟属性:

import mock
import time

class Foo(object):

   def __init__(self):
       self._is_running = False

   @property
   def is_running(self):
       return self._is_running

   @is_running.setter
   def is_running(self, val):
       self._is_running = val 

   def run(self):
       self._is_running = True  # Don't go through the property here.
       while self.is_running:
           print("in here")
           time.sleep(.5)


with mock.patch('__main__.Foo.is_running', new_callable=mock.PropertyMock,
                side_effect=[True, True, False]) as m:
    f = Foo()
    f.run()

输出:

in here
in here
<done>

我想说的是,仅仅为了启用特定的测试方法而对生产实现进行如此大的改变是不值得的。只需让您的测试函数创建一个线程,在一段时间后设置 is_running 即可。

关于python - 在 python 中测试 while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26243334/

相关文章:

ruby-on-rails - 为库模块添加 rspec 测试似乎没有获得期望和匹配器

python - 从 URL 列表(每个 URL 包含一个唯一的表)中抓取表数据,以便将其全部附加到单个列表/数据帧中?

python - 如何在脚本运行时向多处理队列添加更多项目

Python子包从相邻子包导入

ruby-on-rails - 处理后台作业的 Ruby RSpec 最佳实践是什么?我正在做一些不必要的复杂事情吗?

php - 为我使用 Laravel 5.4 测试的 phpunit 播种一次几个表

python - 如何在 python 中创建间隔函数调用的后台线程?

python - AWS CDK : Error when deploying Redis ElastiCache: Subnet group belongs to a different VPC than CacheCluster

java - 使用 Mockito 时,模拟和监视有什么区别?

Spring mvc junit 测试服务