You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Python任务管理器函数编写有效单元测试?

问题:Python任务管理器单元测试无效,全部通过但无法验证结果

我写了一个Python任务管理器程序,开发完成后要给所有函数写单元测试。这些函数互相关联还涉及文件处理,而且几乎没有返回值,没法用断言验证结果。不管测试内容写得多离谱,所有测试全通过,我怀疑测试根本没起到作用。下面是我的任务管理器代码和已写的测试代码,求帮忙解决。


任务管理器程序代码

import datetime

def user_information(ussnm, pssd):
    name = input("Enter your name: ")
    address = input("Enter your address: ")
    age = input("Enter your age: ")
    ussnm_ = f"{ussnm}'s tasks.txt"
    with open(ussnm_, 'a') as f:
        f.write(pssd)
        f.write(f"\nName: {name}\n")
        f.write(f"Address: {address}\n")
        f.write(f"Age: {age}\n")
        f.write("\n")


def signup():
    print("Create a new account")
    username = input("Enter your Username: ")
    password = "" #input("Enter your Password: ")
    while True:
        if len(password) < 8:
            print("Password too short. Try again.")
            password = input("Enter your Password: ")
        else:
            user_information(username, password)
            print("Account created successfully. Log in to your account")
            login()


def login():
    user_name = input("Enter your username: ")
    pass_word = input("Enter the password: ")
    try:
        usernm = f"{user_name}'s tasks.txt"
        with open(usernm, 'r') as f:
            #p is the saved password
            #list index out of range
            p = f.readlines(0)[0]
        if pass_word.strip() == p.strip():
            print("Log in successful!")
            response = input("Choose: \n1 To view your list of tasks \n2 To add task \n3 To update task status \n4 View task status \n")
            #To view list of task
            if response  == '1':
                view_data(usernm)
            #To add task
            elif response == '2':
                task_information(usernm)
            elif response == '3':
                task_update(usernm)
            elif response == '4':
                task_update_viewer(usernm)
            else:
                print("No such option. Try again")
                login()
        else:
            print("Your username or password is incorrect")
            login()

    except Exception as e:
        print(e)
        login()

#To view list of task
def view_data(username):
    with open(username, 'r') as v:
        print(v.read())

#To add task
def task_information(username):
    no_of_task = int(input("How many tasks do you want to add? "))
    with open(username, 'a') as t:
        #doesn't keep asking for tasks for the number of times inputted, only asks once
        for i in range(1, no_of_task+1):
            task = input("Enter a new task: ")
            target = input("How much time do you want to use on this task? ")
            tas = f"Task {str(i)}:"
            tar = f"Target {str(i)}:"

            t.write(f"{tas} {task} \n")
            t.write(f"{tar} {target} \n")
            #to stop adding tasks
            stop = input("Press space bar to stop adding tasks. Otherwise, press enter: ")
            if stop == " ":
                print("Task(s) added")
                break

#To update tasks
def task_update(username):
    #adding a weird name (mayo's tasks.txt's tasks)
    username = f"{username}'s tasks.txt"
    task_completed = input("Enter completed tasks: ")
    task_pending = input("Enter pending tasks: ")
    task_ongoing = input("Enter ongoing tasks: ")

    with open(username, 'a') as up:
        date = str(datetime.datetime.now())
        up.write(f"{date} \n")
        up.write(f"COMPLETED TASK: \n{task_completed} \n")
        up.write(f"ONGOING TASK: \n{task_ongoing} \n")
        up.write(f"PENDING TASKS: \n{task_pending} \n")


def task_update_viewer(username):
    username = f"{username}'s tasks.txt"
    with open(username, 'r') as up_view:
        print(up_view.read())


if __name__ == '__main__':
    print("Welcome to your task manager")
    try:
        a = int(input("Create new account? Type 0 \nAlready a member? Type 1\n"))
        if a == 0:
            signup()
        elif a == 1:
            login()
        else:
            print("No such option")
    except ValueError:
        print("Not a number")

已编写的测试代码

import os.path
from project import user_information
from project import signup
from project import login
from project import view_data
from project import task_information
from project import task_update
from project import task_update_viewer

def test_user_information():
    def user_information(ussnm, pssd):
        if ussnm == "mayo" and pssd == "mayomikun":
            assert os.path.exists("mayo's tasks.txt") == True

def test_signup():
    def signup():
        username = input("Enter your Username: ")
        password = input("Enter your Password: ")
        if username == "mayo" and len(password) == 4:
            assert signup() == login()

def test_login():
    def login():
        user_name = input("Enter your Username: ")
        pass_word = input("Enter your Password: ")
        if user_name == "mayo" and pass_word == "mayomikun":
            assert login() == "Log in successful!"

问题原因及修复方案

1. 测试函数的核心错误

你写的测试里,每个测试函数内部都重新定义了和原函数同名的函数,但从未调用过真正的业务函数,相当于测试函数是空执行,自然全部通过。比如test_user_information里定义了一个新的user_information,但根本没调用导入的user_information,断言也不会触发。

2. 无返回值函数的测试思路

这类函数的行为体现在文件修改、输入输出交互上,需要通过模拟输入、检查文件内容、捕获输出来验证。可以用Python的unittest.mock模块模拟input和print,用临时文件避免污染真实文件。

3. 修复后的测试示例(以user_information为例)

import os
import tempfile
from unittest.mock import patch
from project import user_information

def test_user_information():
    # 创建临时目录,避免影响真实文件
    with tempfile.TemporaryDirectory() as tmpdir:
        original_cwd = os.getcwd()
        os.chdir(tmpdir)
        
        try:
            # 模拟用户输入的姓名、地址、年龄
            with patch('builtins.input', side_effect=["Mayo", "123 Street", "25"]):
                user_information("mayo", "mayomikun")
            
            # 检查文件是否创建
            file_path = "mayo's tasks.txt"
            assert os.path.exists(file_path)
            
            # 检查文件内容是否正确
            with open(file_path, 'r') as f:
                content = f.read()
                assert "mayomikun" in content
                assert "Name: Mayo" in content
                assert "Address: 123 Street" in content
                assert "Age: 25" in content
        finally:
            # 恢复原工作目录
            os.chdir(original_cwd)

4. 其他函数的测试要点

  • signup:模拟用户名和密码输入(符合长度要求/不符合),检查是否调用user_information,是否触发登录。
  • login:模拟用户名密码输入,用临时文件模拟已存在的用户文件,验证登录成功/失败的输出,验证菜单选项的分支是否正确执行。
  • 文件操作函数:统一使用临时文件,测试前后清理,避免残留文件影响后续测试。

5. 原程序的小问题(影响测试)

  • login里的f.readlines(0)[0]是错误用法,readlines的参数是缓冲区大小,不是行数,应该改成f.readline()来读取第一行密码。
  • task_update里重复拼接文件名,导致路径错误(比如传入mayo's tasks.txt后,会变成mayo's tasks.txt's tasks.txt),需要修正逻辑。

内容的提问来源于stack exchange,提问作者Mayo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 14:42:24