DEV Community

Nakaoka Rei
Nakaoka Rei

Posted on

XCTestGen: CLI for automatic XCTest generation using ChatGPT

Introduction

As the title suggests, I created a tool for automatic generation of Swift's XCTest using ChatGPT, which is very popular nowadays. I will briefly explain how I developed it and how to use it.
I would be happy if you starred it.

GitHub logo NakaokaRei / XCTestGen

CLI for automatic XCTest generation using ChatGPT

XCTestGen

CLI for automatic XCTest generation using ChatGPT

Github issues Github forks Github stars Github top language Github license

Installation

Execute the following command from above.

$ git clone git@github.com:NakaokaRei/XCTestGen.git
$ cd XCTestGen
$ swift build -c release
$ cp .build/release/XCTestGen /usr/local/bin/XCTestGen

Usage

Executing the command with the path of the input file and the path of the destination folder will save the unit test code in the destination folder.

$ XCTestGen $OPENAI_KEY "input file path" "output dir path"

e.g. If Sample.swift is input, SampleTests.swift will be created in the output destination.

// Sample.swift
class Sample {
    func sample1(x: Int) -> Int {
        return x + 1
    }

    func sample2(x: String) -> String {
        return x + "sample"
    }
}
Enter fullscreen mode Exit fullscreen mode
// SampleTests.swift
import XCTest
class SampleTests: XCTestCase {

    func test_sample1() {
        // given
        let expectedResult = 11
        let sampleInput = 10
        let sut = Sample()

        // when
        let
Enter fullscreen mode Exit fullscreen mode

Creation of CLI tools

Using Swift Packages, we have created a CLI tool. The template is created by executing the following command under the working directory

$ swift package init --type executable
Enter fullscreen mode Exit fullscreen mode

Automatic generation of XCTest

As the title suggests, ChatGPT is used for automatic generation of XCTests, and the following commands are given to ChatGPT to write 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 {
    // 任意の処理
    }
}
Enter fullscreen mode Exit fullscreen mode

The following libraries were used to utilize OpenAI's API in Swift.

https://github.com/adamrushy/OpenAISwift

Throw the above instruction to ChatGPT and save the response in the specified folder. If you want to know more details, please see the code in the repository.

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
        }
    }
Enter fullscreen mode Exit fullscreen mode

Usage

Installation

Execute the following command

$ git clone git@github.com:NakaokaRei/XCTestGen.git
$ cd XCTestGen
$ swift build -c release
$ cp .build/release/XCTestGen /usr/local/bin/XCTestGen
Enter fullscreen mode Exit fullscreen mode

Generate XCTest

Execute the following command. In order from the first argument, "API Key of OpenAI", "Path of the Swift file for which you want to automatically generate tests", and "Directory of the output destination".

$ XCTestGen $OPENAI_KEY "input file path" "output dir path"
Enter fullscreen mode Exit fullscreen mode

If you give the following code

// Sample.swift
class Sample {
    func sample1(x: Int) -> Int {
        return x + 1
    }

    func sample2(x: String) -> String {
        return x + "sample"
    }
}
Enter fullscreen mode Exit fullscreen mode

The following code is generated and saved

// SampleTests.swift
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)
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

The current issue is that the test code generated from ChatGPT is not checked for grammatical correctness, so I think it would be better to use SwiftLint or other tools to perform at least some checks.
In the future, we plan to add a plugin function to Swift Package Manger so that it can be easily introduced into Xcode projects.

I'm waiting for Issue and PR!!!!

Top comments (0)