0

我正在开发一个脚本来测试另一个程序。基本上,我复制了一个类,其中包含我正在测试的程序所具有的所有功能。为简单起见,假设我只有 2 个函数:set(value) 和 add(value)。set(value) 设置一个累加器值, add(value) 向它添加值;我正在测试一个应该做同样事情的程序。

我还有一个 check() 函数,它验证 set(value) 和 add(value) 操作的累加器值是否与我正在测试的程序检索到的值具有相同的值;所以,在每次操作之后,我想运行这个 check() 函数并确保它们匹配。

为了说明这一点,这里有一个(未经测试的)示例:

def set(self, value):
    self.acc = value
    sendCommandToMyProgram('set', value)

def add(self, value):
    self.acc += value
    sendCommandToMyProgram('add', value)

def check(self):
    return self.acc == sendCommandToMyProgram('check', value)

我想做“测试场景”,比如:

set(1)
check()
add(2)
check()
add(-2)
check()
add(3)

和许多其他人

制作这个“测试场景”脚本的最佳方法是什么?如果它可以与接受不同参数的函数一起工作,那就太好了(在这个例子中,set() 和 add() 都只接收一个参数 - value -,但情况并非总是如此)。

谢谢

4

3 回答 3

1

假设您不想在正常操作期间一直检查该值,那么首先想到的就是内置的单元测试模块

如果您需要做更复杂的事情,而您无法像下面所示那样干净地隔离测试,请查看我必须解决的一些问题。值得注意的是,我最终推出了自己的测试运行器,其行为与单元测试非常相似,但具有更大的控制力。我将在下个月左右将其推向 py-pi。

工作单元测试示例

import unittest

class RealAccumlator(object):
    def __init__(self):
        self.acc = 0

    def add(self, val):
        self.acc += val

    def set(self, val):
        self.acc = val

    def get(self):
        return self.acc


# Using a global variable as I dont know how "sendCommandToMyProgram"
# is used
real_acc = RealAccumlator()


# Test Script

class MyAccumlator(object):
    def __init__(self):
        self.acc = 0

    def add(self, val):
        self.acc += val
        real_acc.add(val)

    def set(self, val):
        self.acc = val
        real_acc.set(val)

    def check(self):
        return self.acc == real_acc.get()

class MockedAccumlatorTests(unittest.TestCase):

    def setUp(self):
        self.acc = MyAccumlator()

    def test_SetFunction(self):
        test_values = range(-10,10)

        # Test the set commands
        for val in test_values:
            self.acc.set(val)
            self.assertTrue(self.acc.check())

    def test_AddFunction(self):
        test_values = range(-10,10)

        # Set the acc to a known value and to a quick test
        self.acc.set(0) 
        self.assertTrue(self.acc.check())

        # Test the add commands
        for val in test_values:
            self.acc.add(val)
            self.assertTrue(self.acc.check())


class RealAccumlatorTests(unittest.TestCase):

    def test_SetFunction(self):
        test_values = range(-10,10)

        # Test the set commands
        for val in test_values:
            real_acc.set(val)
            self.assertEqual(val, real_acc.get())

    def test_AddFunction(self):
        test_values = range(-10,10)

        # Set the acc to a known value and to a quick test
        real_acc.set(0) 
        self.assertEqual(0, real_acc.get())

        # Test the add commands
        expected_value = 0
        for val in test_values:
            expected_value += val
            real_acc.add(val)
            self.assertEqual(expected_value, real_acc.get())

if __name__ == '__main__':
    unittest.main()

根据接受的答案更新

如果这只是一个测试脚本并且你的模拟累加器没有在外面使用,那么这个测试考虑以下模块。 从长远来看,我仍然相信编写单元测试会更好地为您服务

class MyAccumlator(object):
    def __init__(self):
        self.acc = 0

    def add(self, val):
        self.acc += val
        real_acc.add(val)
        assert(self.check())
        return self.check()

    def set(self, val):
        self.acc = val
        real_acc.set(val)
        assert(self.check())
        return self.check()

    def check(self):
        return self.acc == real_acc.get()

这将允许您遍历您想要的任何列表,而无需考虑调用检查函数。提供了两种方法,您可以检查。

  1. assert如果它们不匹配,则 离开调用将引发异常(仅在假设这将作为测试脚本存在的情况下建议)。

  2. 从调用脚本中删除assert并检查返回状态(而不是显式调用也check()可能会清理内容。

于 2013-04-19T04:48:17.690 回答
0

我需要在每次操作后运行“check()”。

我最终创建了“测试场景”,例如:

test_scenarios =
    [
        [
            (obj.set, {1}),
            (obj.add, {5}),
            (obj.add, {-2})
        ],
        [
            (obj.set, {-2}),
            (obj.add, {3}),
            (obj.add, {-5})
            (obj.add, {1})
        ]
    ]

然后我迭代测试场景,基本上调用 test[0](**test[1]) 然后 check()

也许不是最好的解决方案,但我能想到的最好的

于 2013-04-20T04:30:12.707 回答
0

设置值。创建一个包含要添加的值的列表。然后,遍历该列表,运行checkadd使用每个循环。IE:numlist = [1, 2, -2, 3]; for num in numlist: obj.check(); obj.add(num)

于 2013-04-20T05:03:40.610 回答