宠物食谱工具的改进

举报
哦啦啦啦啦 发表于 2026/09/01 15:41:32 2026/09/01
【摘要】 今天做了一件挺完整的事:拿到一个开源小项目,修 bug、加测试、优化 UI,最后发布到华为云开发者作品展览馆。把整个过程记下来,既是复盘,也给类似流程的人一个参考。 一、起点:一个 6 个文件的小项目事情从一个 GitCode 仓库开始:lightyearssssr/pet-food-query——一个宠物食谱查询工具。克隆下来一看,结构非常精简:pet-food-query/├── app...

今天做了一件挺完整的事:拿到一个开源小项目,修 bug、加测试、优化 UI,最后发布到华为云开发者作品展览馆。把整个过程记下来,既是复盘,也给类似流程的人一个参考。

一、起点:一个 6 个文件的小项目

事情从一个 GitCode 仓库开始:lightyearssssr/pet-food-query——一个宠物食谱查询工具。

克隆下来一看,结构非常精简:

pet-food-query/
├── app.py              # Streamlit 前端,5 个页面
├── database.py         # SQLite 数据层
├── seed_data.py        # 22 种预填充食材数据
├── pet_food.db         # SQLite 数据库文件
├── requirements.txt    # 仅 streamlit>=1.30.0
└── README.md

功能挺实用:查食材安全等级、记喂食日志、按间隔天数提醒"可以喂了"还是"还要等"。预填充了 22 种狗的常见食材,包括鸡胸肉、南瓜这类安全食材,以及巧克力、葡萄这类危险食材。

但读了一遍代码,几个问题比较明显。

二、发现的问题

Bug 1:喂食提醒不区分宠物(关键 bug)

这是最严重的一个。database.pyget_last_feeding_date() 有一个 pet_name 参数,但 app.py 的提醒页调用时没传:

# 修复前 — 没传 pet_name
last_date_str = db.get_last_feeding_date(row["id"])

后果是什么?假设你家有旺财和咪咪两只狗,旺财 1 月 10 日吃了鸡胸肉,咪咪 1 月 25 日也吃了。查旺财的提醒时,系统取到的是所有宠物的最新喂食日期(1 月 25 日),而不是旺财自己的(1 月 10 日)。两只宠物共享一个冷却计时,提醒完全错乱。

Bug 2:搜索不支持种类筛选

seed_data.py 里所有食材的 species 都是 "dog",添加食材表单有 dog/cat 选项,但搜索页和提醒页都没有按种类过滤。你加了猫的食材,搜的时候还是全部混在一起。

Bug 3:pet_food.db 提交到了 Git

二进制数据库文件不应该进版本控制——每次运行改动都会产生 diff,仓库会越来越臃肿。而且没有 .gitignore

其他

  • 没有任何测试
  • 搜索是纯 LIKE '%keyword%',粒度较粗
  • UI 是 Streamlit 默认样式,功能可用但缺乏打磨

三、动手改

3.1 修 database

核心改动是给 search_ingredients() 加了 species 参数:

def search_ingredients(keyword, species=None):
    query = "SELECT * FROM ingredients WHERE name LIKE ?"
    params = [f"%{keyword}%"]
    if species:
        query += " AND species = ?"
        params.append(species)
    # ...

同时给 init_db() 加了 db_path 参数,方便测试时用临时数据库,不污染主库。还新增了 get_pet_names() 方法,用于提醒页的下拉框。

3.2 修 app

提醒页是改动最大的地方。加了一个宠物名选择器——如果已经有喂食记录,下拉框会列出已知宠物名;也可以手动输入新名字。选好宠物后,调用时传入 pet_name

# 修复后 — 传入 pet_name
last_date_str = db.get_last_feeding_date(row["id"], pet_name=pet_name)

没选宠物名时,显示一个解释提示,告诉用户为什么要输入:

💡 为什么要输入宠物名?
多宠物家庭中,每只宠物对同一食材有独立的冷却周期。输入宠物名后,提醒会根据该宠物的喂食记录单独计算。

搜索页加了种类筛选下拉框(全部 / 🐶狗 / 🐱猫),食材卡片也加了种类标签显示。添加食材的表单按"分类信息 / 喂食指导 / 营养与注意"三段分组,视觉上更清晰。侧边栏加了版本号 v1.1.0

3.3 加 .gitignore,移除 pet_food.db

git rm --cached pet_food.db   # 从 git 移除,保留本地文件

.gitignore 内容:

pet_food.db
__pycache__/
*.pyc
.venv/
.env
.pytest_cache/

3.4 写测试

用 pytest 写了 24 个单元测试,覆盖 database.py 的所有核心函数。每个测试用 tmp_path fixture 创建临时数据库,互不影响。

其中最关键的一个是 test_pet_name_filter_isolates_pets——专门针对那个 bug 的回归测试:

def test_pet_name_filter_isolates_pets(self, tmp_db):
    """旺财 1/10 喂了鸡胸肉,咪咪 1/25 也喂了。
    查旺财的上次喂食日期应返回 1/10,不是 1/25。"""
    # ...
    result_wangcai = db.get_last_feeding_date(ing_id, pet_name="旺财")
    assert result_wangcai == "2025-01-10"

    result_mimi = db.get_last_feeding_date(ing_id, pet_name="咪咪")
    assert result_mimi == "2025-01-25"

跑一下:

============================== 24 passed in 0.38s ==============================

全绿。

五、回顾

今天的工作量不大,但流程很完整:

阶段 产出
代码审查 发现 4 个问题(1 个关键 bug + 3 个工程问题)
Bug 修复 喂食提醒按宠物名独立计算、搜索加种类筛选
测试 24 个单元测试,0.38s 全绿
UI 优化 搜索筛选、提醒页宠物选择器、表单分组、表格列宽
工程化 .gitignore、移除二进制文件、版本号
发布 封面图 + 架构图 + 详情文章 → 华为云作品展览馆

几个感受:

  1. 那个 pet_name bug 很典型——参数定义了但调用方没传,类型检查也查不出来。如果没有多宠物的实际场景,可能永远不会发现。写测试时专门针对这个场景写了回归测试,以后改代码也不怕再破。

  2. 发布流程的门禁设计值得学习——字体、编码、字形验证,三道关卡层层拦截。在 arm64 Linux 上跑 Playwright 截图确实有不少坑(字体安装、fallback build),但门禁保证了最终产出不会有乱码或豆腐块。

  3. 接口细节容易搞错——POST 还是 GET,路径有没有后缀,参数在 body 还是 header。看文档要仔细,猜是不行的。

如果你也在养宠物,或者对 Streamlit 小工具感兴趣,欢迎来看看。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。