【问题标题】:In order to test a function with unit testing, does it need to have a return value?为了用单元测试来测试一个函数,它需要有一个返回值吗?
【发布时间】:2020-06-05 04:44:56
【问题描述】:

我是 python 新手,正在尝试学习单元测试。我正在使用 pytest 对我的代码运行一些单元测试。与此示例非常相似:

def test_calc_total():
    total = mathlib.calc_total(4,5)
    assert total == 9

我在这里可能不正确,但我了解到,为了使您的函数可测试,它必须返回一个值。所有单元测试都是这样吗?

我发现我的大部分函数都无法测试,因为它们没有返回值。我正在创建一个票务跟踪系统并将票务信息存储在数据框中。这是 TicketDF 类的一部分:

class TicketDF():
    cwd = os.getcwd()
    df = pd.DataFrame()

    def __init__(self, configParser):
        self.populateFilePaths(configParser)
        self.populateAttributes(configParser)
        self.populateTable()

    def populateTable(self):
        if self.doesFileExistAndNotEmpty(self.ticketCSVFilePath):
            self.df = pd.read_csv(self.ticketCSVFilePath, converters={'Comments':literal_eval}) #, 'Attachments':literal_eval})
            self.df.set_index('Ticket ID', inplace=True)

    def populateAttributes(self, configParser):
        self.ticketAttributes =  configParser.getTicketAttributes()

    def populateFilePaths(self, configParser):
        self.ticketCSVFilePath = configParser.getTicketsCSVPath()

    def doesFileExistAndNotEmpty(self, filepath):
        if os.path.exists(filepath) and os.path.getsize(filepath) > 0:
            return True
        else:
            return False

    def getTicketDF(self):
        return self.df

    def addTicketToDF(self, data):
        df = pd.DataFrame (data, columns = self.ticketAttributes)
        df.set_index('Ticket ID', inplace=True)
        self.df = self.df.append(df)
        self.saveDFToCSV()

如您所见,大多数函数,即使是未显示的函数,也没有返回值。编写代码以使所有函数都有返回值是最佳实践吗?或者有没有其他方法可以测试没有返回值的函数?

【问题讨论】:

  • 这些方法正在更改对象或其属性的状态,因此您可以验证值,更改的状态
  • 纯函数——即输出由输入决定的函数——是最容易测试的。您应该尽可能地编写这些类型的函数,因为您可以对行为做出更强有力的保证。
  • 要编写单元测试,您需要调用函数的可观察、可验证、确定性副作用。不需要有返回值。
  • 纯函数存在于计算机世界之外,但是是的——在编程的上下文中,输出将是返回的值。底线是:尽可能保持数据不可变,尝试返回值,并尽量减少副作用;您将有更快乐的时间编写程序。 :-)
  • 这取决于几件事,最终是一个非常哲学的讨论。您要问的基本上是“我应该更喜欢面向对象”还是“我应该更喜欢函数式编程?”两者都有一席之地-我鼓励您阅读两者并自己确定。我更倾向于 FP(所以函数、它们的组成和不变性)——这并不能使它或多或少正确。

标签: python unit-testing pytest


【解决方案1】:

简短的回答是否定的。

测试一个函数取决于能力

  1. 观察函数对程序状态或引起的变化
  2. 访问函数的返回值。

所以,如果一个函数的行为改变了程序的状态并且我们需要测试这个行为,那么我们需要能够访问被改变的状态部分来测试相应的行为。这样的测试可能并不总是依赖于函数的返回值。因此,函数不需要返回可测试的值,但它们确实需要公开与需要测试的行为有关的信息。

有关测试这方面的更多信息,请阅读测试替身。 《xUnit 测试模式》一书中关于间接输入和输出的“使用测试替身”一章是很好的参考。

【讨论】:

  • 请记住,测试副作用的结果可能非常具有挑战性。在 python 中没有隐私这样的概念,但对于其他语言来说,这是一个巨大的问题。
  • 谢谢@Venkatesh!
【解决方案2】:

不,它可能会产生副作用,您可以测试该副作用。

例如,考虑一个写入文件的函数。通过异常报告错误。它没有什么可以归还的。单元测试将调用该函数并检查是否已写入相关文件,并引发各种异常。

另一个例子是改变对象状态的方法调用。您调用该方法并检查对象的状态是否已更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 2022-11-15
    相关资源
    最近更新 更多