XCTestGen: ChatGPTを使ったXCTest自動生成ツール
はじめに
タイトルの通り、今流行りのChatGPTを使ってSwiftのXCTestの自動生成ツールを作りました。どのように開発したのか、使い方などをざっくり解説します。
スターくれたら嬉しいです。
CLIツールの作成
Swift Packagesを使い、CLIツールを作成しました。作業ディレクトリ下で以下のコマンドを実行するとテンプレートが作成されます。詳しい方法はSwift Packagesを使ったCLIの開発はいろんな方が解説しているのでそちらを参照ください。
$ swift package init --type executable
XCTestの自動生成
XCTestの自動生成にはタイトルの通りChatGPTを使用しています。ChatGPTに以下のように命令することで、XCTestを書いてもらいます。
日本語に翻訳すると以下のSwiftコードのユニットテスト(XCTest)を書いてください。出力したものをそのままソースコードとして保存したいので、説明文は不要です。
という命令をしています。
Please write a unit test (XCTest) of the following Swift code. No explanatory text is required as we would like to save your output as source code as is.
// Sample.swift
class Sample {
func sample(input: String) -> String {
// 任意の処理
}
}
SwiftでOpenAIのAPIを利用するには以下のライブラリを使用しました。
上記の命令をChatGPTに投げてレスポンスを指定されたフォルダ内に保存します。詳細を知りたい方はリポジトリのコードをご覧ください。
func generateXCTest() async throws {
let order = "Please write a unit test (XCTest) of the following Swift code. No explanatory text is required as we would like to save your output as source code as is."
let code: String
do {
code = try FileManager.readTextFile(atPath: input)
} catch {
throw XCTestGenError.readCodeError
}
let prompt = order + "\n\n" + code
let openAI = OpenAISwift(authToken: key)
let result = try await openAI.sendCompletion(with: prompt, maxTokens: maxTokens)
guard let testCode = result.choices.first?.text else {
throw XCTestGenError.chatgptResultError
}
do {
try FileManager.saveTextFile(text: testCode, atPath: outputTestsPath())
} catch {
throw XCTestGenError.saveFileError
}
}
使い方
インストール
以下のコマンドを実行します。
$ git clone git@github.com:NakaokaRei/XCTestGen.git
$ cd XCTestGen
$ swift build -c release
$ cp .build/release/XCTestGen /usr/local/bin/XCTestGen
実行
以下のコマンドを実行します。第一引数から順に「OpenAIのAPI Key」、「テストを自動生成したいSwiftファイルのPath」、「出力先のディレクトリ」です。
$ XCTestGen $OPENAI_KEY "input file path" "output dir path"
以下のようなコードを与えた場合は
class Sample {
func sample1(x: Int) -> Int {
return x + 1
}
func sample2(x: String) -> String {
return x + "sample"
}
}
以下のコードが自動生成されます。
import XCTest
class SampleTests: XCTestCase {
func test_sample1() {
// given
let expectedResult = 11
let sampleInput = 10
let sut = Sample()
// when
let result = sut.sample1(x: sampleInput)
// then
XCTAssertEqual(result, expectedResult)
}
func test_sample2() {
// given
let expectedResult = "testsample"
let sampleInput = "test"
let sut = Sample()
// when
let result = sut.sample2(x: sampleInput)
// then
XCTAssertEqual(result, expectedResult)
}
}
最後に
今の課題としてChatGPTから生成されたテストコードが文法的に正しいかなどのチェックが行えてないのでSwiftLintなどを使って最低限のチェックは行なったほうがいいかなと思っています。
今後はSwift Package Mangerのプラグイン機能を追加し、Xcodeプロジェクトへの導入を簡単にできるようにしていく予定です。
Discussion