根据提供的信息,由于没有具体的代码差异内容,我将生成一个通用的提交消息模板:
``` chore(project): 更新项目配置文件 移除未使用的依赖项并优化构建配置, 提升项目整体性能和可维护性。 ```
This commit is contained in:
60
康康Tests/DiaryAssistParseTests.swift
Normal file
60
康康Tests/DiaryAssistParseTests.swift
Normal file
@@ -0,0 +1,60 @@
|
||||
import Testing
|
||||
import Foundation
|
||||
@testable import 康康
|
||||
|
||||
/// 写日记 AI 辅助的纯解析函数 `DiaryAssistService.parseQuestions`。
|
||||
/// 这是「非 JSON 输出」回归的修复重点:解析要对 MNN 的各种畸形输出健壮,
|
||||
/// 彻底解析不出才返回 nil(由 suggest 重试/报错),解析成功但无问题返回 []。
|
||||
/// parseQuestions 随 @MainActor struct 隔离,测试整体标 @MainActor。
|
||||
@MainActor
|
||||
struct DiaryAssistParseTests {
|
||||
|
||||
@Test func parsesStandardWrappedJSON() {
|
||||
let raw = #"{"questions":[{"dim":"起病诱因","q":"什么时候开始的?","fill":"从[时间]开始,"},{"dim":"症状性质","q":"是哪种不适?","fill":"性质是[]"}]}"#
|
||||
let qs = DiaryAssistService.parseQuestions(from: raw)
|
||||
#expect(qs?.count == 2)
|
||||
#expect(qs?.first?.dim == "起病诱因")
|
||||
}
|
||||
|
||||
@Test func parsesMarkdownFenced() {
|
||||
let raw = """
|
||||
```json
|
||||
{"questions":[{"dim":"持续频率","q":"持续多久了?","fill":"已持续[时长]"}]}
|
||||
```
|
||||
"""
|
||||
#expect(DiaryAssistService.parseQuestions(from: raw)?.count == 1)
|
||||
}
|
||||
|
||||
@Test func parsesThinkWrapped() {
|
||||
let raw = "<think>用户头痛,该问起病诱因</think>{\"questions\":[{\"dim\":\"起病诱因\",\"q\":\"何时开始?\",\"fill\":\"从[时间]\"}]}"
|
||||
#expect(DiaryAssistService.parseQuestions(from: raw)?.count == 1)
|
||||
}
|
||||
|
||||
@Test func parsesBareArrayWithoutWrapper() {
|
||||
// MNN 偶尔漏掉外层 {"questions":…},直接吐数组 —— 必须能兜住
|
||||
let raw = #"[{"dim":"加重缓解","q":"做什么会加重?","fill":"[活动]时加重"},{"dim":"生活方式","q":"睡眠如何?","fill":"近期睡眠[]"}]"#
|
||||
#expect(DiaryAssistService.parseQuestions(from: raw)?.count == 2)
|
||||
}
|
||||
|
||||
@Test func repairsTrailingCommaAndSmartQuotes() {
|
||||
// 尾逗号 + 中文弯引号:repairJSON 应修好后正常解析
|
||||
let raw = "{“questions”:[{“dim”:“用药过敏”,“q”:“在吃什么药?”,“fill”:“在服[药名],”},]}"
|
||||
#expect(DiaryAssistService.parseQuestions(from: raw)?.count == 1)
|
||||
}
|
||||
|
||||
@Test func emptyQuestionsArrayReturnsEmptyNotNil() {
|
||||
// 合法 JSON 但没有问题:返回 [](调用方报 .empty,不是 .parseFailed)
|
||||
let qs = DiaryAssistService.parseQuestions(from: #"{"questions":[]}"#)
|
||||
#expect(qs != nil)
|
||||
#expect(qs?.isEmpty == true)
|
||||
}
|
||||
|
||||
@Test func proseReturnsNil() {
|
||||
#expect(DiaryAssistService.parseQuestions(from: "我觉得你可以多问问睡眠情况。") == nil)
|
||||
}
|
||||
|
||||
@Test func unterminatedThinkOnlyReturnsNil() {
|
||||
// 整段都在思考、没吐 JSON 就被截断:strip 后为空 → nil(交给 suggest 重试)
|
||||
#expect(DiaryAssistService.parseQuestions(from: "<think>嗯,用户写了头痛,我应该问") == nil)
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,33 @@ struct VoiceIntentServiceTests {
|
||||
#expect(VoiceIntentService.keywordMatch("写个日记") == .diary)
|
||||
}
|
||||
|
||||
@Test func gibberishReturnsNil() {
|
||||
#expect(VoiceIntentService.keywordMatch("啦啦啦啦") == nil)
|
||||
@Test func unmatchedDefaultsToDiary() {
|
||||
// 不明确命中其它意图时,兜底进日记(最常见、最自由的入口)
|
||||
#expect(VoiceIntentService.keywordMatch("啦啦啦啦") == .diary)
|
||||
#expect(VoiceIntentService.keywordMatch("今天感觉不太舒服") == .diary)
|
||||
#expect(VoiceIntentService.keywordMatch("有点难受") == .diary)
|
||||
}
|
||||
|
||||
// MARK: - 相机类意图的误开防护(本次修复重点)
|
||||
|
||||
@Test func negatedMedicationDoesNotOpenCamera() {
|
||||
// 「没吃药 / 忘了吃药 / 不用吃药」不该归 medication(会弹拍药盒相机),落 diary
|
||||
#expect(VoiceIntentService.keywordMatch("今天太忙,忘了吃药") == .diary)
|
||||
#expect(VoiceIntentService.keywordMatch("我今天没吃药") == .diary)
|
||||
#expect(VoiceIntentService.keywordMatch("医生说先不用吃药") == .diary)
|
||||
}
|
||||
|
||||
@Test func casualReportMentionDoesNotOpenCamera() {
|
||||
// 顺口提到体检/报告,不是要拍报告归档,不该弹文档相机
|
||||
#expect(VoiceIntentService.keywordMatch("下周打算去做个体检") == .diary)
|
||||
#expect(VoiceIntentService.keywordMatch("医生说我报告没什么大问题") == .diary)
|
||||
}
|
||||
|
||||
@Test func genuineCameraIntentsStillMatch() {
|
||||
// 真实的拍药盒 / 归档意图仍要正确命中
|
||||
#expect(VoiceIntentService.keywordMatch("拍个药盒") == .medication)
|
||||
#expect(VoiceIntentService.keywordMatch("我吃了降压药,记一下") == .medication)
|
||||
#expect(VoiceIntentService.keywordMatch("把体检报告存进去") == .archive)
|
||||
#expect(VoiceIntentService.keywordMatch("这张化验单归档") == .archive)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user