接續上一篇「測試 - 使用 AutoFixture 產生指定範圍的隨機數值」的內容,讓我們可以在使用 LatitudeBuilder 和 LongitudeBuilder 時可以設定屬性名稱與範圍。
先處理屬性名稱的部分,以 Latitude 的名稱來說,在命名的時候就會有很多種,當然直接用 Latitude 的也是有,但最常看到的名稱反而是 Lat,而 Coordinate_Y 也是有人在用,然後 Longitude 就可以看到有人用 Lng 或 Lon 或 Coordinate_X 等,一個多人開發的系統以及有好幾代傳承維護開發的系統最容易看到這種明明就是指同一種資料但卻會有各種不同命名的情況發生。
所以當要使用 LatitudeBuilder 產生測試資料的時候,因為原本的做法是直接將屬性名稱寫死在方法裡,在使用上就缺乏了彈性,所以就要對 LatittudeBuilder 做個修改,在使用時讓使用者可以設定屬性名稱。
然後將 Place 類別的屬性 Latitude 的名稱修改為 Lat
測試方法裡的設定
觀察 AutoFixture 所產生的測試資料
知道如何設定屬性名稱,那麼要修改產生資料的範圍上下限就容易了
LatitudeBuilder.cs
using System; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using AutoFixture.Kernel; | |
namespace SampleTests.AutoFixture | |
{ | |
public class LatitudeBuilder : ISpecimenBuilder | |
{ | |
/// <summary> | |
/// 指定屬性名稱. | |
/// </summary> | |
public string PropertyName { get; set; } | |
public double? Minimum { get; set; } | |
public double? Maximum { get; set; } | |
public object Create(object request, ISpecimenContext context) | |
{ | |
var propertyNames = new List<string> | |
{ | |
"Latitude" | |
}; | |
if (string.IsNullOrWhiteSpace(this.PropertyName).Equals(false)) | |
{ | |
propertyNames.Add(this.PropertyName.Trim()); | |
} | |
double minumum = this.Minimum.HasValue && (this.Minimum >= -90 || this.Minimum <= 90) | |
? this.Minimum.Value | |
: -90.0d; | |
double maximum = this.Maximum.HasValue && (this.Maximum >= -90 || this.Maximum <= 90) | |
? this.Maximum.Value | |
: 90.0d; | |
if (minumum > maximum) | |
{ | |
var temp = minumum; | |
minumum = maximum; | |
maximum = temp; | |
} | |
var propertyInfo = request as PropertyInfo; | |
if (propertyInfo != null | |
&& propertyNames.Contains(propertyInfo.Name) | |
&& propertyInfo.PropertyType == typeof(double)) | |
{ | |
return context.Resolve | |
( | |
new RangedNumberRequest(typeof(double), minumum, maximum) | |
); | |
} | |
return new NoSpecimen(); | |
} | |
} | |
} |
設定使用方式
觀察產生的測試資料
LongitudeBuilder.cs
using System; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using AutoFixture.Kernel; | |
namespace SampleTests.AutoFixture | |
{ | |
public class LongitudeBuilder : ISpecimenBuilder | |
{ | |
/// <summary> | |
/// 指定屬性名稱. | |
/// </summary> | |
public string PropertyName { get; set; } | |
public double? Minimum { get; set; } | |
public double? Maximum { get; set; } | |
public object Create(object request, ISpecimenContext context) | |
{ | |
var propertyNames = new List<string> | |
{ | |
"Longitude" | |
}; | |
if (string.IsNullOrWhiteSpace(this.PropertyName).Equals(false)) | |
{ | |
propertyNames.Add(this.PropertyName.Trim()); | |
} | |
double minumum = this.Minimum.HasValue && (this.Minimum >= -180 || this.Minimum <= 180) | |
? this.Minimum.Value | |
: -180.0d; | |
double maximum = this.Maximum.HasValue && (this.Maximum >= -180 || this.Maximum <= 180) | |
? this.Maximum.Value | |
: 180.0d; | |
if (minumum > maximum) | |
{ | |
var temp = minumum; | |
minumum = maximum; | |
maximum = temp; | |
} | |
var propertyInfo = request as PropertyInfo; | |
if (propertyInfo != null | |
&& propertyNames.Contains(propertyInfo.Name) | |
&& propertyInfo.PropertyType == typeof(double)) | |
{ | |
return context.Resolve | |
( | |
new RangedNumberRequest(typeof(double), minumum, maximum) | |
); | |
} | |
return new NoSpecimen(); | |
} | |
} | |
} |
將 Place 類別的屬性 Longitude 名稱修改為 Lng
修改測試方法裡 AutoFixture 的設定
觀察 AutoFixture 所產生的測試資料
這是以座標的 Latitude 和 Longitude 做為案例的操作,也是我實際專案開發時會用到的方式,同樣的方式也可以應用到不同型別、不同情境,實際上的應用就由各位開發人員去做延伸開發。
如果你會在資料容器類別的各個屬性加上 DataAnnotation Attribute 的話,那麼 AutoFixture 會依據各個屬性的 DataAnnotation Attribute 內容產生資料,如此一來是可以不用再另外建立 Builder。(但使用自己客製的 Builder,彈性會比較大一點)
如果…… 我們建立了一堆的 Builder 類別,每一種資料類別的屬性也都不同,在設定 AutoFixture 的 Customizations 時就會使用很多的 Add 方法去加入各種不同的 Builder,一次、兩次、三次去寫重複的程式碼還可以接受,但如果有成千上百的測試方法都要這樣處理的時候就會覺得煩,有沒有什麼方式可以去簡化呢?
下一篇再來說明吧
以上
沒有留言:
張貼留言