テスターちゃん【4コマ漫画】

ソフトウェアテストの用語、やり方などを4コマ漫画でわかりやすく説明する(予定の)ブログです。脱線も多いです。



ChatGPTを用いたTDD part.2 (最初の実装編)

ChatGPTを用いたTDD part.2 (最初の実装編)

ChatGPTを用いたTDD part.1の続きです。

TDDを実践していきます。

時刻とup_timeを抜き出すTODOからやっていきます。

 

最初に、最後に書いた結果を記載すると

テストの実行結果/エラー文をひたすら与えるとChatGPTはテストを満たすコードを書くことができた

です。

 

 

与えられた文字列から時刻とup_timeを抜き出して返す

ファイルの読み込み、csv出力は後にして細かい部品から作ります。

与えられた文字列から時刻とup_timeを抜き出して返す
    文字列を引数として、時刻、up_timeを文字列配列にして返す

TDDなのでまずはテストを作ります。ChatGPTを使います。

テストデータは以下として、この時間とup timeを抜き出して文字列配列で返すことを目標とします。

top - 13:52:54 up 6 min,  0 users,  load average: 0.01, 0.07, 0.03

 

テストコードを書く

 

できました。

一緒にプロダクションコードも書いてくれますが、今回は説明もかねてなのでステップを追ってやっていきます。

import unittest

# テスト対象の関数をインポートするか、実装する必要があります

class TestGetTime(unittest.TestCase):

    def test_get_time(self):
        input_string = "top - 13:52:54 up 6 min,  0 users,  load average: 0.01, 0.07, 0.03"
        expected_result = ["13:52:54", "00:06"]
        self.assertEqual(get_time(input_string), expected_result)

if __name__ == '__main__':
    unittest.main()

 

最初のテスト実行(レッドの状態)

では、このテストを実行します。

`get_time()`のメソッドがないのでエラーが出るはずです。

エラーが出ました。

 

最短でグリーンになるコードを実装

では次は最短でグリーンになるコードを書きます。

できました。自分で書いてもいいけれどChatGPTに書いてもらいました。

staticでもよかったですが、実務でこの記事を応用することを考えて外しています。

class ConvertTop:
    def get_time(self, string):
        return ["13:52:54", "00:06"]

 

-----------------------------------------------------------------------

 

ここでテストもConvertTopを読み込むようにしないといけないのでテストコードを変えます。

テストコードを確認して、your_module_nameを変更します。

これは呼び出すクラスが書かれたファイル名にします。

import unittest

# ConvertTopクラスをインポートします(または実装します)
from ModuleConvertTop import ConvertTop

class TestGetTime(unittest.TestCase):

    def test_get_time(self):
        input_string = "top - 13:52:54 up 6 min,  0 users,  load average: 0.01, 0.07, 0.03"
        expected_result = ["13:52:54", "00:06"]
        # ConvertTopクラスのインスタンスを作成してメソッドを呼び出します
        convert_top_instance = ConvertTop()
        self.assertEqual(convert_top_instance.get_time(input_string), expected_result)

if __name__ == '__main__':
    unittest.main()

 

最初のグリーン

テストを実行します。

通りましたね。

そりゃそう、なのですがまずはグリーンの状態を作ることが大切です。

 

詳細の実装

詳細の実装を行います。ChatGPTが。

最初に通ったget_timeメソッドを書き換えます。

テスト実行

OKがでました。

 

リファクタリング

topコマンドのup timeはやっかいなことに60分未満だと 6 minなどですが、60分を超えると以下のようになります。

top - 00:47:32 up  2:37,  2 users,  load average: 3.01, 1.52, 0.47

これにも対応させたいです。

ちなみに24時間を超えると 1 day となり48時間を超えると 2 daysになるのですが、今回はそこはなしで考えます。

 

では、テストデータのテストを追加します。

ひとつのテストコード内で複数のケースを入れると問題把握しにくくなるのでわけます。

元のテストコードはそのままに、追加で新しいケースをくわえます。

 

-----------------------------------------------------------------------

 

テスト実行をします。

テストが失敗しました。

今のコードでは minでないときの対応ができていないようです。

対応します。ChatGPTが。

 

リファクタリングとテストを繰り返す

プロンプトはシンプルにこのように与えました。

上記のテストコードが通るようなget_timeメソッドを書いてください。

テスト実行します。

失敗です。

 

-----------------------------------------------------------------------

エラーコードを与えて修正してもらいます。

プロンプトは以下のように、失敗した旨とテストから出力された結果だけ与えています。

細かい修正方法などは伝えていません。

このエラーが出ました。修正してください。

(エラー文)

 

コードを張り付けて、テストを実行してみます。

今度は2番目のケースは大丈夫ですが最初のケースが落ちるようになりました。

こういうときケースを分けているとわかりやすいです。

 

-----------------------------------------------------------------------

 

また同様にエラー文を張り付けて修正してもらいます。

今回も同様に、修正の旨とテストから出た結果のみ張り付けています。

テストを実行します。

無事、どちらのテストも通過できました。

これでTDDの流れを一通り行い、TODOの一つが完了しました。

 

このことから、テストの実行結果とエラー文をひたすら与えるとChatGPTはテストを満たすコードを書くことができるようです。

 

ChatGPTを用いたTDD part.3

に続きます。

 

testerchan.hatenadiary.com

 

おまけ

書いたメソッド

def get_time(self, input_string):
        # 時間を抽出する正規表現
        time_pattern = r"\b(\d{2}:\d{2}:\d{2})\b"
        # 稼働時間を抽出するための正規表現("up 6 min" および "up  2:37" の両方に対応)
        uptime_pattern = r"up\s+*1 if uptime_match.group(2) else 0
            uptime_minutes = int(uptime_match.group(3))
            uptime_formatted = f"{uptime_hours:02}:{uptime_minutes:02}"
        else:
            uptime_formatted = "00:00"  # 稼働時間が見つからない場合のデフォルト値

        return [time, uptime_formatted]

 

書いたテストコード

def test_get_time(self):
        input_string = "top - 13:52:54 up 6 min,  0 users,  load average: 0.01, 0.07, 0.03"
        expected_result = ["13:52:54", "00:06"]
        # ConvertTopクラスのインスタンスを作成してメソッドを呼び出します
        convert_top_instance = ConvertTop()
        self.assertEqual(convert_top_instance.get_time(input_string), expected_result)

    def test_get_time_additional(self):
        input_string = "top - 00:47:32 up  2:37,  2 users,  load average: 3.01, 1.52, 0.47"
        expected_result = ["00:47:32", "02:37"]
        convert_top_instance = ConvertTop()
        self.assertEqual(convert_top_instance.get_time(input_string), expected_result)

 

 

 

*1:\d+):)?(\d+)( min)?,"


        # 時間を検索して抽出
        time_match = re.search(time_pattern, input_string)
        if time_match:
            time = time_match.group(1)
        else:
            time = "00:00:00"  # 時間が見つからない場合のデフォルト値

        # 稼働時間を検索して抽出
        uptime_match = re.search(uptime_pattern, input_string)
        if uptime_match:
            uptime_hours = int(uptime_match.group(2