【问题标题】:Clarification of Test Driven Development in Python澄清 Python 中的测试驱动开发
【发布时间】:2021-01-11 04:44:09
【问题描述】:

我想知道是否可以对 TDD 和一般测试进行一些澄清。我正在使用python 编写我的程序,并使用pytest 作为我的测试框架。

到目前为止,我一直在做的方式,首先编写这些测试,已经开始让我的大脑对某些任务采取务实的方法。

  1. 除了 3 个类变量之外的所有内容都是在编写测​​试之前编写的,这是否意味着我在技术上没有遵循 TDD?
  2. 为了清楚起见,我是否应该先为未实现的方法编写整个测试,然后创建方法和功能以使测试通过?
  3. 我遵循 TDD 的主要目标是让每一个测试都通过,无论我对测试数据进行什么更改?(确实如此)(因此消除了潜在的错误?)
  4. 是否应该对班级进行大量测试(取决于班级人数)?
  5. 根据下面的代码,你能告诉我我是否在正确的路径上

供您参考的代码

import pytest
import os
import sys

path = os.path.dirname(os.path.abspath(__file__))
path = path.replace("\\pytest", "")
sys.path.append(path)
path += "\\pyffi"
sys.path.append(path)

from NifExplorer import NifExplorer
from NifExplorer import NifFormat

@pytest.fixture(autouse=True, scope='session')
def setup_nifExplorer():
    Explorers = []

    explorer = NifExplorer()
    explorer.SetBlockType(NifFormat.NiNode)
    explorer.SetResultPath("\\pytest\\results")
    explorer.SetSearchPath("\\pytest\\nif\\base")

    explorer2 = NifExplorer()
    explorer2.SetBlockType(NifFormat.ATextureRenderData)
    explorer2.SetResultPath("\\pytest\\results")
    explorer2.SetSearchPath("\\pytest\\nif\\base")

    explorer3 = NifExplorer()
    explorer3.SetBlockType("NiNode")
    explorer3.SetResultPath("\\pytest\\testResults")
    explorer3.SetSearchPath("\\pytest\\nif\\base")

    Explorers.append(explorer)
    Explorers.append(explorer2)
    Explorers.append(explorer3)


    return Explorers   

@pytest.mark.usefixtures("setup_nifExplorer")
class TestNifExplorer:
    def NifExlorer_BlockType_Is_Not_None(self, setup_nifExplorer):
        assert setup_nifExplorer.BlockType != None

    def NifExplorer_SearchPath_Is_Not_None(self, setup_nifExplorer):
        assert setup_nifExplorer.SearchPath != None

    def NifExplorer_ResultPath_Is_Not_None(self, setup_nifExlorer):
        assert setup_nifExlorer.ResultPath != None
        
    @pytest.mark.parametrize('funcs', (NifExplorer_SearchPath_Is_Not_None, NifExplorer_ResultPath_Is_Not_None, NifExlorer_BlockType_Is_Not_None))
    def test_NifExplorer_Variables_Equal_Not_None(self, setup_nifExplorer, funcs):
        for obj in setup_nifExplorer:
            funcs(self,obj)
        
    def NifExplorer_ResultPath_Directory_Exists(self, setup_nifExplorer):
        assert os.path.exists(setup_nifExplorer.ResultPath) == True

    def NifExplorer_SearchPath_Directory_Exists(self, setup_nifExplorer):
        assert os.path.exists(setup_nifExplorer.SearchPath) == True

    def NifExplorer_SearchPath_Directory_Contains_No_Forward_Slashes(self, setup_nifExplorer):
        assert setup_nifExplorer.SearchPath.count('/') < 1

    def NifExplorer_ResultPath_Directory_Contains_No_Forward_Slashes(self, setup_nifExplorer):
        assert setup_nifExplorer.ResultPath.count('/') < 1

    @pytest.mark.parametrize('funcs', [NifExplorer_ResultPath_Directory_Exists, NifExplorer_SearchPath_Directory_Exists, NifExplorer_SearchPath_Directory_Contains_No_Forward_Slashes, NifExplorer_ResultPath_Directory_Contains_No_Forward_Slashes])
    def test_NifExplorer_Directories_Exist_And_Paths_Contain_No_Forward_Slashes(self, setup_nifExplorer, funcs):
        for obj in setup_nifExplorer:
            funcs(self,obj)

    def NifExplorer_SearchPath_Contains_Nif_Files_Recursively(self, setup_nifExplorer):
        assert setup_nifExplorer.DirectoryContainsNifRecursively(setup_nifExplorer.SearchPath) == True

    @pytest.mark.parametrize('funcs', [NifExplorer_SearchPath_Contains_Nif_Files_Recursively])
    def test_NifExplorer_SearchPath_Contains_Nif_Files(self, setup_nifExplorer, funcs):
        for obj in setup_nifExplorer:
            funcs(self,obj)
if __name__ == "__main__":
    pytest.main()

【问题讨论】:

    标签: python tdd pytest


    【解决方案1】:

    除了 3 个类变量之外的所有内容都是在编写测​​试之前编写的,这是否意味着我在技术上没有遵循 TDD?

    如果您在进行需要的测试之前编写任何“真实”代码,那么您就没有遵循 TDD。没关系——TDD 不一定是在所有情况下都可以使用的最佳工具。但是,当您处于 TDD 有意义的情况下,则首先编写测试。

    我是否应该先为未实现的方法编写整个测试,然后创建方法和功能以便测试通过?

    这取决于您遵循谁的指导。 Robert Martin 建议您编写足够多的测试以使其失败,然后通过该测试,然后编写更多测试,然后通过该测试,依此类推,直到测试完成。他称之为纳米循环。 Martin 建议将此作为一种技术,以重现与 Kent Beck 合作的经验。

    但是,当 Kent Beck 自己描述 TDD 时,他谈到要编写一个完整的测试,然后一次解决其中的问题。

    我自己发现 Beck 的风格更适合我,尤其是在可以自动填充一些缺失代码的编码环境中。所以我会专注于测试的设计,直到我满意为止,然后让IDE创建我需要通过测试的骨架代码,最后填写细节。

    我遵循 TDD 的主要目标是让每一个测试都通过吗

    测试确实是“错误检测器”;目标是创建能够提供价值且不会出错的代码。

    TDD 的好处之一是,这种仪式大大减少了您在任何时候必须处理的“错误”数量。是的,这意味着纪律是我们几乎总是处于两种状态之一,或者(a)我们编写的所有测试都通过了,或者(b)除了我们编写的测试之一之外的所有测试都通过了。

    一个类的测试是否应该有很大的数量(取决于类的大小)?

    不一定大小;复杂性可能是一个更好的衡量标准——有多少不同的输入类?您通常需要从每个样本中至少抽取一个样本,以确保您需要的所有行为都存在。

    这里有一个常见的例子:想象一个函数,它以公历年作为输入,如果该年是闰年则返回 true。我们关心的输入类

    • 不能被 4 整除的年份
    • 年份可以被 4 整除,但不能被 100 整除
    • 年份可以被 100 整除,但不能被 400 整除
    • 年可被 400 整除

    那么四个“测试”?

    你能告诉我我是否在正确的道路上

    很难说。然而,有几个想法很突出。

    大多数实际工作包括“复杂的代码”和“难以测试的代码”。一个有用的技巧是设计你的代码,让复杂的代码易于测试,而难以测试的代码则简单到明显没有缺陷。

    “难以测试”包括依赖于共享可变状态(如文件系统)的行为。所以我们经常会选择文件系统代码过于简单而无法破解的设计,将所有分支放在其他地方,然后彻底测试分支代码。

    此外,测试设计是一件事。特别是,我们通常希望优先考虑使测试一目了然。反过来,这通常意味着您将把一个测试的所有代码放在一起,而不是将一堆“设置”代码放在一个地方,而您的断言放在另一个地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-26
      • 2010-09-07
      • 2013-04-25
      • 1970-01-01
      • 2011-09-09
      • 2012-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多