mirror of
https://github.com/mii443/AzooKeyKanaKanjiConverter.git
synced 2025-08-22 15:05:26 +00:00
feat: add tests for typo
This commit is contained in:
@ -28,8 +28,9 @@ public struct ConvertRequestOptions: Sendable {
|
||||
/// - textReplacer: 予測変換のための置換機を指定します。
|
||||
/// - specialCandidateProviders: 特殊変換を実施する変換関数を挿入します
|
||||
/// - metadata: メタデータを指定します。詳しくは`ConvertRequestOptions.Metadata`を参照してください。
|
||||
public init(N_best: Int = 10, requireJapanesePrediction: Bool, requireEnglishPrediction: Bool, keyboardLanguage: KeyboardLanguage, englishCandidateInRoman2KanaInput: Bool = false, fullWidthRomanCandidate: Bool = false, halfWidthKanaCandidate: Bool = false, learningType: LearningType, maxMemoryCount: Int = 65536, shouldResetMemory: Bool = false, dictionaryResourceURL: URL, memoryDirectoryURL: URL, sharedContainerURL: URL, textReplacer: TextReplacer, specialCandidateProviders: [any SpecialCandidateProvider]?, zenzaiMode: ZenzaiMode = .off, preloadDictionary: Bool = false, metadata: ConvertRequestOptions.Metadata?) {
|
||||
public init(N_best: Int = 10, needTypoCorrection: Bool? = nil, requireJapanesePrediction: Bool, requireEnglishPrediction: Bool, keyboardLanguage: KeyboardLanguage, englishCandidateInRoman2KanaInput: Bool = false, fullWidthRomanCandidate: Bool = false, halfWidthKanaCandidate: Bool = false, learningType: LearningType, maxMemoryCount: Int = 65536, shouldResetMemory: Bool = false, dictionaryResourceURL: URL, memoryDirectoryURL: URL, sharedContainerURL: URL, textReplacer: TextReplacer, specialCandidateProviders: [any SpecialCandidateProvider]?, zenzaiMode: ZenzaiMode = .off, preloadDictionary: Bool = false, metadata: ConvertRequestOptions.Metadata?) {
|
||||
self.N_best = N_best
|
||||
self.needTypoCorrection = needTypoCorrection
|
||||
self.requireJapanesePrediction = requireJapanesePrediction
|
||||
self.requireEnglishPrediction = requireEnglishPrediction
|
||||
self.keyboardLanguage = keyboardLanguage
|
||||
@ -86,6 +87,7 @@ public struct ConvertRequestOptions: Sendable {
|
||||
specialCandidateProviders.append(.commaSeparatedNumber)
|
||||
|
||||
self.N_best = N_best
|
||||
self.needTypoCorrection = nil
|
||||
self.requireJapanesePrediction = requireJapanesePrediction
|
||||
self.requireEnglishPrediction = requireEnglishPrediction
|
||||
self.keyboardLanguage = keyboardLanguage
|
||||
@ -157,6 +159,7 @@ public struct ConvertRequestOptions: Sendable {
|
||||
public var requireJapanesePrediction: Bool
|
||||
public var requireEnglishPrediction: Bool
|
||||
public var keyboardLanguage: KeyboardLanguage
|
||||
public var needTypoCorrection: Bool?
|
||||
// KeyboardSettingのinjection用途
|
||||
public var englishCandidateInRoman2KanaInput: Bool
|
||||
public var fullWidthRomanCandidate: Bool
|
||||
@ -183,6 +186,7 @@ public struct ConvertRequestOptions: Sendable {
|
||||
static var `default`: Self {
|
||||
Self(
|
||||
N_best: 10,
|
||||
needTypoCorrection: nil,
|
||||
requireJapanesePrediction: true,
|
||||
requireEnglishPrediction: true,
|
||||
keyboardLanguage: .ja_JP,
|
||||
|
@ -605,7 +605,7 @@ import EfficientNGram
|
||||
/// - N_best: 計算途中で保存する候補数。実際に得られる候補数とは異なる。
|
||||
/// - Returns:
|
||||
/// 結果のラティスノードと、計算済みノードの全体
|
||||
private func convertToLattice(_ inputData: ComposingText, N_best: Int, zenzaiMode: ConvertRequestOptions.ZenzaiMode) -> (result: LatticeNode, lattice: Lattice)? {
|
||||
private func convertToLattice(_ inputData: ComposingText, N_best: Int, zenzaiMode: ConvertRequestOptions.ZenzaiMode, needTypoCorrection: Bool) -> (result: LatticeNode, lattice: Lattice)? {
|
||||
if inputData.convertTarget.isEmpty {
|
||||
return nil
|
||||
}
|
||||
@ -625,11 +625,6 @@ import EfficientNGram
|
||||
self.previousInputData = inputData
|
||||
return (result, nodes)
|
||||
}
|
||||
#if os(iOS)
|
||||
let needTypoCorrection = true
|
||||
#else
|
||||
let needTypoCorrection = false
|
||||
#endif
|
||||
|
||||
guard let previousInputData else {
|
||||
debug("\(#function): 新規計算用の関数を呼びますA")
|
||||
@ -698,7 +693,14 @@ import EfficientNGram
|
||||
// DicdataStoreにRequestOptionを通知する
|
||||
self.sendToDicdataStore(.setRequestOptions(options))
|
||||
|
||||
guard let result = self.convertToLattice(inputData, N_best: options.N_best, zenzaiMode: options.zenzaiMode) else {
|
||||
#if os(iOS)
|
||||
let needTypoCorrection = options.needTypoCorrection ?? true
|
||||
#else
|
||||
let needTypoCorrection = options.needTypoCorrection ?? false
|
||||
#endif
|
||||
|
||||
|
||||
guard let result = self.convertToLattice(inputData, N_best: options.N_best, zenzaiMode: options.zenzaiMode, needTypoCorrection: needTypoCorrection) else {
|
||||
return ConversionResult(mainResults: [], firstClauseResults: [])
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ public import Foundation
|
||||
public extension ConvertRequestOptions {
|
||||
static func withDefaultDictionary(
|
||||
N_best: Int = 10,
|
||||
needTypoCorrection: Bool? = nil,
|
||||
requireJapanesePrediction: Bool,
|
||||
requireEnglishPrediction: Bool,
|
||||
keyboardLanguage: KeyboardLanguage,
|
||||
@ -29,13 +30,26 @@ public extension ConvertRequestOptions {
|
||||
#else
|
||||
let dictionaryDirectory = Bundle.module.resourceURL!.appendingPathComponent("Dictionary", isDirectory: true)
|
||||
#endif
|
||||
|
||||
var specialCandidateProviders = [any SpecialCandidateProvider]()
|
||||
if typographyLetterCandidate {
|
||||
specialCandidateProviders.append(.typography)
|
||||
}
|
||||
if unicodeCandidate {
|
||||
specialCandidateProviders.append(.unicode)
|
||||
}
|
||||
specialCandidateProviders.append(.emailAddress)
|
||||
specialCandidateProviders.append(.timeExpression)
|
||||
specialCandidateProviders.append(.calendar)
|
||||
specialCandidateProviders.append(.version)
|
||||
specialCandidateProviders.append(.commaSeparatedNumber)
|
||||
|
||||
return Self(
|
||||
N_best: N_best,
|
||||
needTypoCorrection: needTypoCorrection,
|
||||
requireJapanesePrediction: requireJapanesePrediction,
|
||||
requireEnglishPrediction: requireEnglishPrediction,
|
||||
keyboardLanguage: keyboardLanguage,
|
||||
typographyLetterCandidate: typographyLetterCandidate,
|
||||
unicodeCandidate: unicodeCandidate,
|
||||
englishCandidateInRoman2KanaInput: englishCandidateInRoman2KanaInput,
|
||||
fullWidthRomanCandidate: fullWidthRomanCandidate,
|
||||
halfWidthKanaCandidate: halfWidthKanaCandidate,
|
||||
@ -46,6 +60,7 @@ public extension ConvertRequestOptions {
|
||||
memoryDirectoryURL: memoryDirectoryURL,
|
||||
sharedContainerURL: sharedContainerURL,
|
||||
textReplacer: textReplacer,
|
||||
specialCandidateProviders: specialCandidateProviders,
|
||||
zenzaiMode: zenzaiMode,
|
||||
preloadDictionary: preloadDictionary,
|
||||
metadata: metadata
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import KanaKanjiConverterModuleWithDefaultDictionary
|
||||
@testable import KanaKanjiConverterModuleWithDefaultDictionary
|
||||
import XCTest
|
||||
|
||||
final class ConverterTests: XCTestCase {
|
||||
@ -17,9 +17,10 @@ final class ConverterTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
func requestOptions() -> ConvertRequestOptions {
|
||||
func requestOptions(needTypoCorrection: Bool = false) -> ConvertRequestOptions {
|
||||
.withDefaultDictionary(
|
||||
N_best: 10,
|
||||
needTypoCorrection: needTypoCorrection,
|
||||
requireJapanesePrediction: false,
|
||||
requireEnglishPrediction: false,
|
||||
keyboardLanguage: .ja_JP,
|
||||
@ -56,21 +57,23 @@ final class ConverterTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testRoman2KanaFullConversion() async throws {
|
||||
for needTypoCorrection in [true, false] {
|
||||
do {
|
||||
let converter = await KanaKanjiConverter()
|
||||
var c = ComposingText()
|
||||
c.insertAtCursorPosition("azuーkiーhasinjidainokiーboーdoapuridesu", inputStyle: .roman2kana)
|
||||
let results = await converter.requestCandidates(c, options: requestOptions())
|
||||
let results = await converter.requestCandidates(c, options: requestOptions(needTypoCorrection: needTypoCorrection))
|
||||
XCTAssertEqual(results.mainResults.first?.text, "azooKeyは新時代のキーボードアプリです")
|
||||
}
|
||||
do {
|
||||
let converter = await KanaKanjiConverter()
|
||||
var c = ComposingText()
|
||||
c.insertAtCursorPosition("youshoukikaratenisusuieiyakyuushourinjikenpounadosamazamanasupoーtuwokeikennsinagarasodatishougakkouzidaiharosanzerusukinkounitaizaisiteorigoruhuyatenisuwonaratteita", inputStyle: .roman2kana)
|
||||
let results = await converter.requestCandidates(c, options: requestOptions())
|
||||
let results = await converter.requestCandidates(c, options: requestOptions(needTypoCorrection: needTypoCorrection))
|
||||
XCTAssertEqual(results.mainResults.first?.text, "幼少期からテニス水泳野球少林寺拳法など様々なスポーツを経験しながら育ち小学校時代はロサンゼルス近郊に滞在しておりゴルフやテニスを習っていた")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1文字ずつ変換する
|
||||
// memo: 内部実装としては別のモジュールが呼ばれるのだが、それをテストする方法があまりないかもしれない
|
||||
@ -237,6 +240,37 @@ final class ConverterTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
// typo訂正アリ
|
||||
do {
|
||||
let cases: [(input: String, expect: String)] = [
|
||||
("たいかくせい", "大学生"),
|
||||
("きみのことかすき", "君のことが好き"),
|
||||
("おへんとうをもつていく", "お弁当を持っていく"),
|
||||
]
|
||||
|
||||
// full input
|
||||
var options = requestOptions(needTypoCorrection: true)
|
||||
options.requireJapanesePrediction = false
|
||||
for (input, expect) in cases {
|
||||
let converter = await KanaKanjiConverter()
|
||||
var c = ComposingText()
|
||||
sequentialInput(&c, sequence: input, inputStyle: .direct)
|
||||
let results = await converter.requestCandidates(c, options: options)
|
||||
XCTAssertEqual(results.mainResults.first?.text, expect)
|
||||
}
|
||||
// gradual input
|
||||
for (input, expect) in cases {
|
||||
let converter = await KanaKanjiConverter()
|
||||
var c = ComposingText()
|
||||
for char in input {
|
||||
c.insertAtCursorPosition(String(char), inputStyle: .direct)
|
||||
let results = await converter.requestCandidates(c, options: options)
|
||||
if c.input.count == input.count {
|
||||
XCTAssertEqual(results.mainResults.first?.text, expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 変換結果が比較的一意なテストケースを無数に持ち、一定の割合を正解することを要求する
|
||||
|
Reference in New Issue
Block a user