[架構][技巧] AI UnitTest:讓ChatGPT幫助你編寫更好的測試代碼

更新於 發佈於 閱讀時間約 27 分鐘

在軟體開發領域,AI工具的演進提供新方法來編寫和測試代碼。利用AI來輔助撰寫單元測試已經成為一種新的測試策略。

透過提示AI來撰寫測試代碼,可以更快速地生成測試用例,找出潛在的缺陷並解決問題,從而提高軟體開發的效率和品質。



流程

首先對ChatGPT描述使用的技術架構和想進行的步驟,接著在步驟中和ChatGPT互動並請它提供合適的單元測試代碼。(詳細內容請參考下方的”完整流程”)



優點

採用AI輔助撰寫單元測試的效果比預計還好,特別是測試範圍和效率

前者你可以明確指定AI提供測試的範圍,也可以要求AI提供容易遺漏的測試用例,擴大合理的涵蓋範圍。

後者比起手動輸入測試代碼,透過AI產生測試代碼的速度也會有顯著的提升。

提升速度這一點相當重要,許多排斥撰寫單元測試的開發者,主要原因為在開發時程中很難再排入撰寫單元測試的時間,更不用說當業務邏輯變動之後,與其對應的單元測試也必須重構修改,因此拒絕學習或撰寫單元測試。

若透過AI產生或重構測試代碼,就能大幅降低花費撰寫單元測試的時間,也能順便開啟通往TDD的大道。



缺點

不洩漏敏感訊息的情況下,將想測試的邏輯完整表達給ChatGPT是一個可能的問題,因為我測試的邏輯很簡單,ChatGPT很清楚溫度轉換公式,提供測試代碼相當容易,但若你想測試的演算法或情境特別複雜,要完整的表達清楚就沒這麼簡單了。



總結

在現階段透過AI來輔助撰寫單元測試是一種可以探索的方式,事實上整個過程就是簡單的TDD開發流程,而ChatGPT就是我的結對編程同伴,而且這個同伴很有耐心,有求必應,沒有偏見(?)。

在測試範圍和效率都是AI的優勢,能夠大幅度縮短撰寫測試代碼的時間,但在不洩漏敏感資訊的情況下,如何表達複雜的測試邏輯會是一個可能的問題。



完整流程

以下是透過提示ChatGPT來產生測試代碼,再讓開發者來撰寫產品代碼的過程。

首先告訴ChatGPT系統簡述和技術架構和需求,包含測試庫的要求(MSTest)。

目前的系統是一個溫度轉換程式。
技術架構:C#,Winform,用於模型的測試庫(MSTest)。
所有的程式碼都應該使用上述的技術架構來撰寫。
需求:程式應該提供華氏和攝氏的溫度轉換並以測試驅動開發來撰寫。
請你只提供單元測試,我再回答是否通過你的單元測試,以這種循環方式來完成整個過程

好的,以下是使用 MSTest 撰寫的兩個單元測試。一個用於驗證華氏到攝氏的溫度轉換,另一個用於驗證攝氏到華氏的溫度轉換。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using YourTemperatureConversionNamespace; // 請將此替換為您的溫度轉換類別的命名空間

namespace TemperatureConversionTests
{
[TestClass]
public class TemperatureConversionTest
{
[TestMethod]
public void TestFahrenheitToCelsius()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputFahrenheit = 32.0;
double expectedCelsius = 0.0;

// Act
double actualCelsius = converter.FahrenheitToCelsius(inputFahrenheit);

// Assert
Assert.AreEqual(expectedCelsius, actualCelsius, 0.01);
}

[TestMethod]
public void TestCelsiusToFahrenheit()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputCelsius = 0.0;
double expectedFahrenheit = 32.0;

// Act
double actualFahrenheit = converter.CelsiusToFahrenheit(inputCelsius);

// Assert
Assert.AreEqual(expectedFahrenheit, actualFahrenheit, 0.01);
}
}
}

這裡假設你有一個 TemperatureConverter 類別,並且該類別有兩個方法:FahrenheitToCelsius 和 CelsiusToFahrenheit。這些方法都接受一個雙精度浮點數(double)並返回一個雙精度浮點數。這些方法應該進行溫度轉換。

請注意,這些測試中的精確度為 0.01,這意味著如果實際結果與預期結果之間的差異小於或等於 0.01,則該測試將被認為是通過的。

請將此單元測試代碼添加到你的測試項目中,並運行這兩個測試。如果你的溫度轉換代碼正確,則這兩個測試都應該通過。

接著就可以建立Winform專案,並在該專案中新增一個TemperatureConversionTest測試類別並直接貼上ChatGPT提供的完整代碼。

當然,執行測試一定會失敗,因為根本還沒有TemperatureConverter類別。

(如果對測試驅動開發有點了解,應該可以發現這也是驅動測試開發的流程,甚至也可以把ChatGPT當作結對編程的對象)

最後再根據ChatGPT提供的單元測試,實作被測代碼。為了避免洩漏敏感訊息,被測代碼不會提供給ChatGPT。

被測代碼如下

public class TemperatureConverter
{
public double FahrenheitToCelsius(double fahrenheit)
{
if (fahrenheit < -459.67)
{
throw new ArgumentOutOfRangeException("The Fahrenheit temperature cannot be less than -459.67");
}
return (fahrenheit - 32) * 5 / 9;
}

public double CelsiusToFahrenheit(double celsius)
{
if (celsius < -273.15)
{
throw new ArgumentOutOfRangeException("The Celsius temperature cannot be less than -273.15");
}
return (celsius * 9 / 5) + 32;
}
}

接著回答ChatGPT,已可通過單元測試,請再提供更多的單元測試。而且在這裡明確指定測試範圍為極限值

我已可通過你提供的單元測試,請再提供更多的單元測試,主要測試範圍為極限值
---
using Microsoft.VisualStudio.TestTools.UnitTesting;
using YourTemperatureConversionNamespace; // 請將此替換為您的溫度轉換類別的命名空間

namespace TemperatureConversionTests
{
[TestClass]
public class TemperatureConversionTest
{
[TestMethod]
public void TestFahrenheitToCelsiusAbsoluteZero()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputFahrenheit = -459.67;
double expectedCelsius = -273.15;

// Act
double actualCelsius = converter.FahrenheitToCelsius(inputFahrenheit);

// Assert
Assert.AreEqual(expectedCelsius, actualCelsius, 0.01);
}

[TestMethod]
public void TestCelsiusToFahrenheitAbsoluteZero()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputCelsius = -273.15;
double expectedFahrenheit = -459.67;

// Act
double actualFahrenheit = converter.CelsiusToFahrenheit(inputCelsius);

// Assert
Assert.AreEqual(expectedFahrenheit, actualFahrenheit, 0.01);
}

[TestMethod]
public void TestFahrenheitToCelsiusHighTemperature()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputFahrenheit = 212.0;
double expectedCelsius = 100.0;

// Act
double actualCelsius = converter.FahrenheitToCelsius(inputFahrenheit);

// Assert
Assert.AreEqual(expectedCelsius, actualCelsius, 0.01);
}

[TestMethod]
public void TestCelsiusToFahrenheitHighTemperature()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputCelsius = 100.0;
double expectedFahrenheit = 212.0;

// Act
double actualFahrenheit = converter.CelsiusToFahrenheit(inputCelsius);

// Assert
Assert.AreEqual(expectedFahrenheit, actualFahrenheit, 0.01);
}
}
}

把上述的單元測試新增到TemperatureConversionTest類別,並執行所有的單元測試,被測代碼可以成功通過單元測試!

接下來想對輸入的不合法數值做一些處理,所以要求ChatGPT對溫度低於絕對零度撰寫測試代碼

我已經可以通過你提供的單元測試,但如果輸入的溫度低於絕對零度,我想丟出一個異常,你可以寫出這種測試嗎?

當然可以。在這裡,我將為溫度低於絕對零度的情況寫出兩個測試。我們期望方法在這種情況下拋出一個異常。

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using YourTemperatureConversionNamespace; // 請將此替換為您的溫度轉換類別的命名空間

namespace TemperatureConversionTests
{
[TestClass]
public class TemperatureConversionTest
{
[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void TestFahrenheitToCelsiusBelowAbsoluteZero()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputFahrenheit = -500.0; // Less than absolute zero

// Act
converter.FahrenheitToCelsius(inputFahrenheit);

// Assert is handled by the ExpectedException attribute
}

[TestMethod]
[ExpectedException(typeof(ArgumentOutOfRangeException))]
public void TestCelsiusToFahrenheitBelowAbsoluteZero()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputCelsius = -300.0; // Less than absolute zero

// Act
converter.CelsiusToFahrenheit(inputCelsius);

// Assert is handled by the ExpectedException attribute
}
}
}

在這兩個測試中,我們使用了 ExpectedException 屬性來指定我們期望方法在給定的情況下拋出的異常類型。在這種情況下,我們期望方法在溫度低於絕對零度時拋出 ArgumentOutOfRangeException。如果你的溫度轉換方法正確地處理了這種情況,那麼這些測試應該會通過。

把ChatGPT新增的測試代碼貼到測試類別之後,執行單元測試應該會失敗。因為在TemperatureConverter沒有根據輸入的不合法數據丟出異常。

回頭修改TemperatureConverter,主要針對華氏低於-459.67和攝氏低於-243.15,丟出異常

public class TemperatureConverter
{
public double FahrenheitToCelsius(double fahrenheit)
{
if (fahrenheit < -459.67)
{
throw new ArgumentOutOfRangeException("The Fahrenheit temperature cannot be less than -459.67");
}
return (fahrenheit - 32) * 5 / 9;
}

public double CelsiusToFahrenheit(double celsius)
{
if (celsius < -273.15)
{
throw new ArgumentOutOfRangeException("The Celsius temperature cannot be less than -273.15");
}
return (celsius * 9 / 5) + 32;
}
}

完成後順利通過單元測試!

最後想請ChatGPT提供它覺得缺乏的單元測試。

我已經可以通過單元測試了,最後我想請提供你覺得缺乏的單元測試

很好,你已經涵蓋了一些重要的測試案例。除了我們已經討論過的測試案例,我們還可以添加一些邊界測試和特殊值測試。以下是一些我們可以添加的額外測試:

  1. 輸入為零的情況:零度華氏對應的攝氏溫度為 -17.78°C,零度攝氏對應的華氏溫度為 32°F。
  2. 一些隨機值的測試:選擇一些隨機的華氏和攝氏溫度值,檢查轉換是否正確。

以下是相應的單元測試:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using YourTemperatureConversionNamespace; // 請將此替換為您的溫度轉換類別的命名空間

namespace TemperatureConversionTests
{
[TestClass]
public class TemperatureConversionTest
{
[TestMethod]
public void TestFahrenheitToCelsiusZero()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputFahrenheit = 0.0;
double expectedCelsius = -17.78;

// Act
double actualCelsius = converter.FahrenheitToCelsius(inputFahrenheit);

// Assert
Assert.AreEqual(expectedCelsius, actualCelsius, 0.01);
}

[TestMethod]
public void TestCelsiusToFahrenheitZero()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputCelsius = 0.0;
double expectedFahrenheit = 32.0;

// Act
double actualFahrenheit = converter.CelsiusToFahrenheit(inputCelsius);

// Assert
Assert.AreEqual(expectedFahrenheit, actualFahrenheit, 0.01);
}

[TestMethod]
public void TestFahrenheitToCelsiusRandom()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputFahrenheit = 45.0; // A random Fahrenheit value
double expectedCelsius = 7.22; // Corresponding Celsius value

// Act
double actualCelsius = converter.FahrenheitToCelsius(inputFahrenheit);

// Assert
Assert.AreEqual(expectedCelsius, actualCelsius, 0.01);
}

[TestMethod]
public void TestCelsiusToFahrenheitRandom()
{
// Arrange
TemperatureConverter converter = new TemperatureConverter();
double inputCelsius = 20.0; // A random Celsius value
double expectedFahrenheit = 68.0; // Corresponding Fahrenheit value

// Act
double actualFahrenheit = converter.CelsiusToFahrenheit(inputCelsius);

// Assert
Assert.AreEqual(expectedFahrenheit, actualFahrenheit, 0.01);
}
}
}

這些測試將增加對你的溫度轉換程式碼的信心。如果所有這些測試都通過了,那麼你的溫度轉換程式碼在這些測試覆蓋的範圍內應該是正確的。請注意,單元測試能幫助我們提高對程式碼的信心,但並不能保證程式碼百分之百的正確。例如,有可能存在我們尚未考慮到的邊界情況或特殊情況。因此,雖然這些測試是一個很好的起點,但可能仍需要進一步的測試和審查來確保程式碼的健壯性。

留言
avatar-img
留言分享你的想法!
avatar-img
寫狐的沙龍
1會員
6內容數
目前專注於軟體設計架構領域,旨在分享並提供良好且合適的原則 / 模式 / 系統 / 開發法。
寫狐的沙龍的其他內容
2022/07/05
前同事阿強是開發部門的技術強者,最近因為大功一件加上考績滿分,被老闆提拔為經理。 看起來阿強走路有風。沒想到在聚會時卻跑來跟我訴苦。 “唉我喜歡技術也專精技術,可是我從沒管過人,也沒想過要管人” “你有跟你老闆談過你沒意願嗎?” “好吧…(難道技術能力強也代表管理能力強嗎)” 答案是不一定!
Thumbnail
2022/07/05
前同事阿強是開發部門的技術強者,最近因為大功一件加上考績滿分,被老闆提拔為經理。 看起來阿強走路有風。沒想到在聚會時卻跑來跟我訴苦。 “唉我喜歡技術也專精技術,可是我從沒管過人,也沒想過要管人” “你有跟你老闆談過你沒意願嗎?” “好吧…(難道技術能力強也代表管理能力強嗎)” 答案是不一定!
Thumbnail
2021/12/10
甚麼是技術雷達? 技術雷達是一種評估工具,用來判斷軟體領域中各種技術並對這些技術應採取什麼行動的方法。(來源為 ThoughtWorks,參閱這裡) 象限 技術雷達本身是一個切割成4等份的圓形,這4等份各為技巧(左上),工具(左下),語言框架(右上),平台(右下),代表技術種類(在官方網站中稱為象限
Thumbnail
2021/12/10
甚麼是技術雷達? 技術雷達是一種評估工具,用來判斷軟體領域中各種技術並對這些技術應採取什麼行動的方法。(來源為 ThoughtWorks,參閱這裡) 象限 技術雷達本身是一個切割成4等份的圓形,這4等份各為技巧(左上),工具(左下),語言框架(右上),平台(右下),代表技術種類(在官方網站中稱為象限
Thumbnail
2021/12/08
無論是參與面試或釐清需求,系統設計常常令人感到困惑,不知如何進行。 我想,原因大概有兩種。 首先,不同領域的系統通常都有不同的設計要素,如何找出這些要素進行提問? 其次,即便提出疑問找出重點,接下來要如何針對這些要素進行高層設計或規劃? 《系統設計面試指南》對於系統設計的初步規劃或高層結構提供合適的
Thumbnail
2021/12/08
無論是參與面試或釐清需求,系統設計常常令人感到困惑,不知如何進行。 我想,原因大概有兩種。 首先,不同領域的系統通常都有不同的設計要素,如何找出這些要素進行提問? 其次,即便提出疑問找出重點,接下來要如何針對這些要素進行高層設計或規劃? 《系統設計面試指南》對於系統設計的初步規劃或高層結構提供合適的
Thumbnail
看更多
你可能也想看
Thumbnail
Hi,大家好,我是茶桁。 很遗憾在上一讲,也就是第12讲的时候,咱们对于利用AI写一个VBA宏来执行Excel任务的过程并不顺利,仔细想来既然大家都在这里看这个系列文章了,应该也基本都会Python的,所以一个Excel自动化也并无太大影响,毕竟,这种商业软件的集成一定是早晚的事情,咱们也不必在这
Thumbnail
Hi,大家好,我是茶桁。 很遗憾在上一讲,也就是第12讲的时候,咱们对于利用AI写一个VBA宏来执行Excel任务的过程并不顺利,仔细想来既然大家都在这里看这个系列文章了,应该也基本都会Python的,所以一个Excel自动化也并无太大影响,毕竟,这种商业软件的集成一定是早晚的事情,咱们也不必在这
Thumbnail
最近,企業越來越注重提升業務績效,尤其是在繁忙的商業環境中。所以,為了讓業務開發更加簡便和高效,在現代商業世界中出現了各種各樣的新技術,其中一種就是聊天機器人。ChatGPT是如今最受歡迎的聊天機器人之一,它能夠與用戶自然溝通,並給出有用資訊。在此篇文章中我們將探討如何結合ChatGPT實現業務開發
Thumbnail
最近,企業越來越注重提升業務績效,尤其是在繁忙的商業環境中。所以,為了讓業務開發更加簡便和高效,在現代商業世界中出現了各種各樣的新技術,其中一種就是聊天機器人。ChatGPT是如今最受歡迎的聊天機器人之一,它能夠與用戶自然溝通,並給出有用資訊。在此篇文章中我們將探討如何結合ChatGPT實現業務開發
Thumbnail
在軟體開發領域,AI工具的演進提供新方法來編寫和測試代碼。利用AI來輔助撰寫單元測試已經成為一種新的測試策略。 透過提示AI來撰寫測試代碼,可以更快速地生成測試用例,找出潛在的缺陷並解決問題,從而提高軟體開發的效率和品質。
Thumbnail
在軟體開發領域,AI工具的演進提供新方法來編寫和測試代碼。利用AI來輔助撰寫單元測試已經成為一種新的測試策略。 透過提示AI來撰寫測試代碼,可以更快速地生成測試用例,找出潛在的缺陷並解決問題,從而提高軟體開發的效率和品質。
Thumbnail
ChatGPT 是一款基於 GPT 技術的自然語言處理工具。那 GPT 是什麼呢?GPT 指的是 Generative Pre-trained Transformer,它是一種神經網絡模型,能夠處理自然語言的文本數據,學習文本之間的關聯,並且能夠根據這些關聯自動生成新的文本。ChatGPT 正是利用
Thumbnail
ChatGPT 是一款基於 GPT 技術的自然語言處理工具。那 GPT 是什麼呢?GPT 指的是 Generative Pre-trained Transformer,它是一種神經網絡模型,能夠處理自然語言的文本數據,學習文本之間的關聯,並且能夠根據這些關聯自動生成新的文本。ChatGPT 正是利用
Thumbnail
自從ChatGPT更新到第四版,討論度更甚以往。在回應內容品質提升的同時,大家開始擔心它對學習的影響。以評量為例,我對ChatGPT帶來的影響並不悲觀。
Thumbnail
自從ChatGPT更新到第四版,討論度更甚以往。在回應內容品質提升的同時,大家開始擔心它對學習的影響。以評量為例,我對ChatGPT帶來的影響並不悲觀。
Thumbnail
不論你的使用場景是什麼,都需要對 ChatGPT 下指令,初學者可能會在網路上複製各路大神分享的指令來用,本篇文章將分享如何把常用指令透過簡單的代碼快速輸出!利用自然輸入法中「文字範本」的功能,來結合近期火紅的 ChatGPT、midjourney 和 New Bing 來有效提升工作效率。
Thumbnail
不論你的使用場景是什麼,都需要對 ChatGPT 下指令,初學者可能會在網路上複製各路大神分享的指令來用,本篇文章將分享如何把常用指令透過簡單的代碼快速輸出!利用自然輸入法中「文字範本」的功能,來結合近期火紅的 ChatGPT、midjourney 和 New Bing 來有效提升工作效率。
Thumbnail
身為一個實在不太怕被AI搶飯碗的專業文案(我覺得它寫的成果對創意廣告文案來說,我直接寫出完稿,比設法詠唱問題更快,但企劃、論述、增長改短這些工作上面,我則已經在使用它來降低成本了),忽然很好奇我到底有哪些事情可以請它幫忙,哪些事情還是自己動手比較又快又好? 今天我就
Thumbnail
身為一個實在不太怕被AI搶飯碗的專業文案(我覺得它寫的成果對創意廣告文案來說,我直接寫出完稿,比設法詠唱問題更快,但企劃、論述、增長改短這些工作上面,我則已經在使用它來降低成本了),忽然很好奇我到底有哪些事情可以請它幫忙,哪些事情還是自己動手比較又快又好? 今天我就
Thumbnail
現在很紅的 ChatGPT,不知道大家試過了沒有,如果還沒有可以趕快去試看看,看看這個新的AI應用,可以幫忙我們做哪些事情,是不是可以讓我們的做事效率更好,或是跟他一起合作創造出一些什麼不同的變化。我自己試了一下,也把我試過的問答寫在這篇文章下面,他在文案生成、軟體開發方面是可以有蠻大的幫助,雖然目
Thumbnail
現在很紅的 ChatGPT,不知道大家試過了沒有,如果還沒有可以趕快去試看看,看看這個新的AI應用,可以幫忙我們做哪些事情,是不是可以讓我們的做事效率更好,或是跟他一起合作創造出一些什麼不同的變化。我自己試了一下,也把我試過的問答寫在這篇文章下面,他在文案生成、軟體開發方面是可以有蠻大的幫助,雖然目
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News