用pytest编写实例方法单元测试的正确方法。

问题描述 投票:1回答:1

我想为类写单元测试,有几种数据转换的方法。

高层次的。

class my_class:

    def __init__(self, file):
        # read data out of .yml config file
        config = read_data_from_yml_config(file)
        self.value1 = config["value1"]
        self.value2 = config["value2"]

    def get_and_transform(self):
        data_dict = self.get_data()
        transformed_data = self.transform_data(data_dict)

        return transformed_data

    def get_data(self):
        data_dict = request_based_on_value1(self.value1)
        return data_dict

    def transform_data(self, data_dict):
        trnsf = transform1(data_dict, self.value2)

        return trnsf

在这里,我有几个问题。这里主要测试的是 my_class.transform_data(). 它把一个dict作为输入,把它读成一个pandas数据框架并做一些转换。

在我的理解中,我需要几个夹具 d1, d2, d3,...(因为对 data_dict),它们代表my_class.transform_data()的不同测试用例输入。由于我想确保输出结果与预期一致,我将定义我的预期输出。

o1 # expected output for transform_data(d1)
o2, o3, ... # respectively

我有几个问题

  1. 这种方法正确吗?
  2. 我应该如何以及在哪里指定 d1, d2, ... 和 o1, o2,....? 我要么在 test_my_class.py-文件或将 d1_sample.pkl, ... 存储在 tests/ 文件夹.在这里,我会选择一个最小的例子,为两个 do
  3. 由于转型中 transform_data 也取决于属性 self.value2,我如何传递不同的值给 value2 的实例而不创建 my_class?

总的来说,我也不太清楚我是在 "对象 "层面还是在 "方法 "层面进行测试。在上面,我描述了一个 "方法 "的方法(因为我主要对以下结果感兴趣 transform_data). 另一种方法是提供不同的.yml文件,从而创建不同的测试实例的 my_class.

def yml1():
    config = read_in_yml1()
    return config

# and so on for different configurations.

然后进行测试。

@pytest.mark.parametrize("test_input, expected", [(yml1, ???), (yml2, ???)])
def test_my_class():
    test_class = my_class(file)

    assert test_class.transform_data == expected

然而,作为函数输入 my_class.transform_data() 并不(直接)取决于内容。yml1而不是反应。my_class.get_data(),这似乎没什么意义。我如何测试不同输入值的 data_dict?

在这种情况下,正确的编写单元测试的方法是什么?

python unit-testing testing pytest
1个回答
1
投票

我不是什么专家,但我觉得你的问题很有趣,所以我打算试着发一个既仔细又有建设性的答案。

  1. 你的方法是验证... transform_data 在我看来,对输入和输出对的行为符合预期是有效的。单元测试验证了你的源代码中最小的组件("单元")的行为是否符合预期,我想说的是,你的三个方法的行为是不同的,足以让这些方法成为单元。
  2. 如果你不确定是在你的测试文件内部还是在外部的.pkl文件中声明输入字典和预期输出对,我猜测这些输入输出对要么很大(大小)要么很多(数量)。
    • 在第一种情况下,你可以声明一个默认的: data_dict 输入字典和一个默认的预期输出作为两个固定装置,您可以在以后的时候 猴皮 内的测试函数。你可以用不同的值来设定测试函数的参数,这些值对应于 data_dict 词典,然后 monkeypatch的默认元素 data_dict 灯具 与这些参数化的值。
    • 在第二种情况下,我认为最好将测试用例的数量减少到几个相关的用例,并尽量将它们的输入输出规范保留在测试文件中。
  3. 你可以在测试文件中传递不同的 value2 猴子补丁的 value2 的实例的属性。my_class. 然而,你需要至少声明一次这样的实例(无论是在你的函数内部还是外部)。

就像我上面写的那样,在 "方法级 "而不是 "对象级 "上进行测试对我来说也是面向对象的软件。提供不同的.yml文件并创建不同的类实例(所以像你说的那样在 "对象级 "上进行测试)在我看来,这是做测试的第一步。融合 测试。最后一点我可能错了,但希望有人能改进我在这一点或其他方面的回答:)。

© www.soinside.com 2019 - 2024. All rights reserved.