使用用户输入进行 Python 3 单元测试 [英] Python 3 Unit tests with user input

查看:28
本文介绍了使用用户输入进行 Python 3 单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Python 单元测试完全陌生.我需要将它用于我必须提交的项目.我有点知道从哪里开始,看起来我们基本上将测试参数放入我们在程序中定义的函数中,然后我们输入了预期的结果.如果输出的是预期结果,我们就OK,否则我们就会Failure,或者一个错误.

I'm absolutely brand new to Python unit test. I need to use it for a project I have to submit. I sort of have an idea of where to begin, it looks like we basically put in test parameters to functions we have defined in our program and we enter the expected result. If the expected result is output, we get OK, otherwise we will get Failure, or an error.

所以我的问题是我有多个用户输入存储在 for 循环或 while 循环内的变量中.我什至不知道从哪里开始为他们设置测试值.

So my problem is that I have multiple user inputs stored into variables that are within for loops or while loops. I don't know where to even begin with this to set test values in for them.

这是我所有的代码:

studentTripExpenses = {}

def dictCreate(studentAmount):
    for i in range(0, studentAmount):
        studentName = input("What is the name of the student? ")
        expenseList = []
        print("Enter 'done' to move to the next student.")
        while True:
            expense = input("What is the cost of this expense? ")
            if expense.lower() == 'done':
                break
            elif (float(expense) >= 0) or (float(expense) < 0):
                expenseList.append(float(expense))
            elif not expense.isdigit():
                print("Please enter a number or enter 'done' to move on.")
        studentTripExpenses[studentName] = expenseList
    return studentTripExpenses

def studentCost(dct):
    for i in dct:
        #Variable for individual costs of student
        personalCost = 0
        #Determines the total cost for each student
        for x in dct[i]:
            personalCost = personalCost + x
        #Sets each students value to their total cost to two decimal places
        dct[i] = float("%.2f" % personalCost)
    return dct

def amountsDue(expenseLst, studentAvgPrice):
        #Runs through the dictionary of students and individual total trip costs
        for key in expenseLst:
            maxPerson = max(expenseLst, key=expenseLst.get)
            costDifference = 0
            #Determines who owes who how much money
            if max(expenseLst.values()) > expenseLst[key]:
                costDifference = studentAvgPrice-expenseLst[key]
                if (costDifference < 0):
                    costDifference = costDifference * -1
                print("%s owes %s $%.2f" % (key, maxPerson, costDifference))

def main():
    numOfStudents = int(input("How many students are going on the trip? "))
    studentCostDict = dictCreate(numOfStudents)
    studentTripExpenses = studentCost(studentCostDict)

    totalCost = 0

    #Gets the total cost for all students
    for key in (studentTripExpenses):
        totalCost = totalCost + studentTripExpenses[key]

    #Changes the total cost to 2 decimal places
    totalCost = float("%.2f" % totalCost)

    #Determines the average amount spent per student
    avgCost = float("%.2f" % (totalCost/len(studentTripExpenses)))

    amountsDue(studentTripExpenses, avgCost)

main()

推荐答案

您可以使用 mocking,在这里您可以使用测试提供的版本替换函数或类.您可以使用 unittest.mock() 模块执行此操作.

You can use mocking, where you replace a function or class with a test-supplied version. You can do this with the unittest.mock() module.

在这种情况下,您可以修补模块中的 input() 名称;将调用模拟对象而不是内置函数:

In this case, you can patch the input() name in your module; instead of the built-in function, the mock object will be called:

from unittest import mock
from unittest import TestCase
import module_under_test

class DictCreateTests(TestCase):
    @mock.patch('module_under_test.input', create=True)
    def testdictCreateSimple(self, mocked_input):
        mocked_input.side_effect = ['Albert Einstein', '42.81', 'done']
        result = dictCreate(1)
        self.assertEqual(result, {'Albert Einstein': [42.81]})

因为 input 在你的模块中不存在(它是一个内置函数),我告诉 mock.patch() 装饰器 来创建名称;现在将使用这个 input 而不是内置函数.

Because input doesn't exist in your module (it is a built-in function), I told the mock.patch() decorator to create the name; now this input will be used instead of the built-in function.

side_effect 属性 允许你声明多个结果;每次调用模拟时,它都会返回该列表中的下一个值.所以第一次返回'Albert Einstein',下次返回'42.81',依此类推

The side_effect attribute lets you state multiple results; each time the mock is called, it'll return the next value in that list. So the first time 'Albert Einstein' is returned, the next time '42.81', etc.

一起,这可以让您模拟实际的用户输入.

Together, this lets you simulate actual user inputs.

如果你的测试正确,你会注意到你的函数有一个错误;当输入除 done 或有效数值以外的任何内容时,float() 调用将抛出 ValueError 异常.您需要重新编写代码来解决这个问题.尝试使用 mocked_input.side_effect = ['Albert Einstein', 'Not avenue', '42.81', 'done'] 来触发错误.

If you do your test right, you'll notice that there is a bug in your function; the float() call will throw a ValueError exception when anything other than done or a valid numeric value is entered. You need to rework your code to account for that. Try with mocked_input.side_effect = ['Albert Einstein', 'Not an expense', '42.81', 'done'] to trigger the bug.

这篇关于使用用户输入进行 Python 3 单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆