Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何为一系列数据转换编写单元测试?_Python_R_Unit Testing_Tdd_Testthat - Fatal编程技术网

Python 如何为一系列数据转换编写单元测试?

Python 如何为一系列数据转换编写单元测试?,python,r,unit-testing,tdd,testthat,Python,R,Unit Testing,Tdd,Testthat,我试图学习TDD,同时编写一个脚本,在一系列函数中转换其输入数据。无论我是用python还是R编写,问题都是类似的。我想这更多地与TDD理解有关 # Look of main in python def main(): data = get_data() data_a = transform_fun1(data) data_b = transform_fun2(data_a) data_c = transform_fun3(data_b) ....

我试图学习TDD,同时编写一个脚本,在一系列函数中转换其输入数据。无论我是用python还是R编写,问题都是类似的。我想这更多地与TDD理解有关

# Look of main in python
def main():
    data = get_data()
    data_a = transform_fun1(data)
    data_b = transform_fun2(data_a)
    data_c = transform_fun3(data_b)
    ....
    return data_x

# Look of main in R
main <- function() {
    data <- get_data() %>%
      transform_fun1() %>%
      transform_fun2() %>%
      transform_fun3() %>%
      ...
    data_x
}
我还尝试在每个步骤之间添加fixture(至少在python中是这样),但看起来也不太理想

--编辑-- 试图勾勒出Unreason的答案是什么样的

def transformV1(data):
     return data + x

def transformV2(data):
     return transformV1(data) + y

def transformV3(data):
     return transformV2(data) + z

def main():
     data = get_data()
     return transformV3(data)
一开始它看起来相当干净,但随着我越来越深入,我开始在每次测试中复制越来越多的主要内容,这闻起来不太好。复制主过程的整个部分与单元测试的想法不太直观

# in python (pytest)
def test_transform_fun_n(data):
    data_a = transform_fun1(data)
    data_b = transform_fun2(data_a)
    ...
    data_n = transform_fun_n(data_n-1)
    assert data_n == blabla

# in R (testthat)
test_that("transform_fun_n do what I expect", {
    data_a <- transform_fun1(data)
    data_b <- transform_fun2(data_a)
    ...
    data_n <- transform_fun_n(data_n-1)
    expect_that(data_n, equals(blabla))
})
是的,你说得对。代码试图告诉您,您的规范(和生产代码)是在错误的抽象级别编写的

def test_transformV1(data, expected):
    actual = transformV1(data)
    assert actual == expected

def main():
    data = getData()
    return transformV1(data)
当需求发生变化时,您将使用新的规范编写一个新的测试

def test_transformV2(data, expected):
    actual = transformV2(data)
    assert actual == expected

def test_transformV1(data, expected):
    actual = transformV1(data)
    assert actual == expected

def main():
    data = getData()
    return transformV2(data)
这里的关键思想是(a)单元测试执行生产代码提供的功能(b)新需求意味着一个新功能——新功能可以用其他功能实现,但测试只是检查新功能是否返回正确的结果

如果main很难测试(这是一个常见的问题),那么您希望尽可能地使它变薄

让它简单到没有明显的缺陷

长链的转换需要从外壳到核心进行重构;给一个名字,等等

你的意思是代码应该写得更像我在问题末尾添加的内容吗


是的,这就是想法:命令shell使用与其中一个测试相同的入口点访问功能核心

既然您已经确定了一系列转换函数,那么合乎逻辑的操作过程就是单独测试它们。另一方面,测试
main()

因为每个函数都将前一个函数的结果作为输入,所以您可能会试图在测试执行中链接它们,就像它们在主程序中链接一样。但是,这种方法会破坏单元测试方法,可能会让您专注于最终结果的快乐路径,从而阻止您在过程的每一步探索输入值的潜在问题边缘情况


相反,请尝试依赖函数输入类型来生成一系列具有不同输入值的测试,这些输入值反映了每个函数的不同场景。您甚至可以使用基于属性的快速检查工具为您生成随机值。

非常感谢您的回答。我还是有点困惑。你的意思是代码应该像我在问题末尾添加的那样编写(代码在注释中看起来没有格式)。我开始在每个测试中复制越来越多的main-在
main()
中是否有比代码示例中显示的调用序列更复杂的逻辑?目前我设置了一些值,但是没有什么东西不能放在transformVx(数据)函数中。