187 lines
5.5 KiB
Dart
187 lines
5.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:kouyu_english/core/courses/courses.dart';
|
|
|
|
/// The free "初次见面" scene, which is always open.
|
|
LessonDialogue get meet => sceneById('a0-meet').script;
|
|
|
|
void main() {
|
|
group('对话任务校验', () {
|
|
test('每个对话都为每一轮声明了任务标签', () {
|
|
for (final entry in segmentDialogues.entries) {
|
|
final script = entry.value;
|
|
expect(
|
|
script.taskLabels.length,
|
|
script.prompts.length,
|
|
reason: '${entry.key} 的任务标签数量要和回合数一致',
|
|
);
|
|
expect(
|
|
script.requiredTerms.length,
|
|
script.prompts.length,
|
|
reason: '${entry.key} 的校验词组数量要和回合数一致',
|
|
);
|
|
for (final group in script.requiredTerms) {
|
|
expect(group, isNotEmpty);
|
|
}
|
|
}
|
|
expect(meet.taskLabels.length, meet.prompts.length);
|
|
expect(meet.requiredTerms.length, meet.prompts.length);
|
|
});
|
|
|
|
test('示范答案能通过对应回合的校验', () {
|
|
for (final entry in {...segmentDialogues, 'scene': meet}.entries) {
|
|
final script = entry.value;
|
|
for (var stage = 0; stage < script.hints.length; stage++) {
|
|
expect(
|
|
matchesDialogueStage(script, stage, script.hints[stage]),
|
|
isTrue,
|
|
reason: '${entry.key} 第 ${stage + 1} 轮的示范答案应当通过',
|
|
);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('跑题回答不再因为关键词沾边而通过', () {
|
|
// 旧实现用 text.contains('it'),下面这些句子全部会被判为完成任务。
|
|
expect(
|
|
matchesDialogueStage(segmentDialogues['a0-05-a']!, 0, 'I did it.'),
|
|
isFalse,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(segmentDialogues['a0-08-c']!, 1, 'It is good.'),
|
|
isFalse,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(segmentDialogues['a0-09-a']!, 2, 'I like tea.'),
|
|
isFalse,
|
|
);
|
|
expect(matchesDialogueStage(meet, 0, 'Hello.'), isFalse);
|
|
expect(matchesDialogueStage(meet, 1, 'I am good.'), isFalse);
|
|
});
|
|
|
|
test('自由场景接受同样正确的其他说法', () {
|
|
// 旧正则只认 good/okay/tired,也不认 my name's。
|
|
expect(matchesDialogueStage(meet, 0, "My name's Shen."), isTrue);
|
|
expect(matchesDialogueStage(meet, 0, 'I am Shen.'), isTrue);
|
|
expect(matchesDialogueStage(meet, 2, "I'm fine, thanks."), isTrue);
|
|
expect(matchesDialogueStage(meet, 2, 'I am great!'), isTrue);
|
|
expect(matchesDialogueStage(meet, 3, 'Where are you from?'), isTrue);
|
|
expect(matchesDialogueStage(meet, 3, 'Do you like tea?'), isTrue);
|
|
});
|
|
|
|
test('只写半句不算完成任务', () {
|
|
expect(matchesDialogueStage(meet, 0, "I'm"), isFalse);
|
|
expect(
|
|
matchesDialogueStage(segmentDialogues['a0-04-c']!, 0, 'My number is'),
|
|
isFalse,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(
|
|
segmentDialogues['a0-04-c']!,
|
|
0,
|
|
'My number is one-three-eight.',
|
|
),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('拼读和数字这类结构化要求可以识别', () {
|
|
expect(
|
|
matchesDialogueStage(segmentDialogues['a0-02-a']!, 1, 'S-H-E-N'),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('拼读忽略大小写和连字符', () {
|
|
final spelling = segmentDialogues['a0-02-a']!;
|
|
for (final answer in [
|
|
'A-A-A',
|
|
'aaa',
|
|
'AAA',
|
|
'a-a-a',
|
|
'A - A - A',
|
|
'a a a',
|
|
'Shen',
|
|
'S-H-E-N.',
|
|
'She-n',
|
|
'L-I',
|
|
'Li',
|
|
'My name is Alex. A-L-E-X.',
|
|
]) {
|
|
expect(
|
|
matchesDialogueStage(spelling, 1, answer),
|
|
isTrue,
|
|
reason: answer,
|
|
);
|
|
}
|
|
for (final answer in ['a', 'My name is Alex.', '123', '---']) {
|
|
expect(
|
|
matchesDialogueStage(spelling, 1, answer),
|
|
isFalse,
|
|
reason: answer,
|
|
);
|
|
}
|
|
expect(
|
|
matchesDialogueStage(
|
|
segmentDialogues['a0-08-c']!,
|
|
1,
|
|
"It's three o'clock.",
|
|
),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(segmentDialogues['a0-08-c']!, 1, "It's Monday."),
|
|
isFalse,
|
|
);
|
|
});
|
|
|
|
test('任务标签可用于提示和总结', () {
|
|
expect(dialogueTaskLabel(meet, 0), '介绍姓名');
|
|
expect(dialogueTaskLabel(meet, 9), '完成本轮任务');
|
|
});
|
|
|
|
test('输入校验忽略多余空格与大小写', () {
|
|
expect(
|
|
matchesDialogueStage(meet, 0, " MY NAME IS SHEN "),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(
|
|
segmentDialogues['a0-02-a']!,
|
|
1,
|
|
" S H E N ",
|
|
),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(
|
|
segmentDialogues['a0-04-c']!,
|
|
0,
|
|
"MY NUMBER IS ONE-THREE-EIGHT",
|
|
),
|
|
isTrue,
|
|
);
|
|
expect(
|
|
matchesDialogueStage(
|
|
segmentDialogues['a0-08-c']!,
|
|
1,
|
|
"IT'S THREE O'CLOCK",
|
|
),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('给 AI 的可用词表随课程递增且不越界', () {
|
|
final first = taughtLanguageUpTo('a0-01');
|
|
final later = taughtLanguageUpTo('a0-09');
|
|
expect(first, isNotEmpty);
|
|
expect(later.length, greaterThan(first.length));
|
|
expect(first.every(later.contains), isTrue);
|
|
expect(later.length, lessThanOrEqualTo(a0TaughtLanguage.length));
|
|
expect(
|
|
first.any((word) => word.toLowerCase().contains('coffee')),
|
|
isFalse,
|
|
);
|
|
});
|
|
});
|
|
}
|