2014-12-19 29 views
0

什麼是測試的東西,不等於精確值,如大圓計算的最佳方式:如何測試正確的大圓距離計算?

/// <summary> 
/// Get the great circle distance (shortest distance possible) between two points in km. 
/// </summary> 
/// <param name="endPoint">end point</param> 
/// <returns>the great circle distance in km</returns> 
public double GreatCircleDistanceInKm(IGeoPoint endPoint) 
{ 
    var earthRadius = Constants.EARTH_RADIUS_KM; 
    var diffLat = Utility.DegreesToRadians(endPoint.Latitude - this.Latitude); 
    var diffLong = Utility.DegreesToRadians(endPoint.Longitude - this.Longitude); 

    var a = Math.Sin(diffLat/2) * Math.Sin(diffLat/2) + 
      Math.Cos(Utility.DegreesToRadians(this.Latitude)) * Math.Cos(Utility.DegreesToRadians(endPoint.Latitude)) * 
      Math.Sin(diffLong/2) * Math.Sin(diffLong/2); 
    var c = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a))); 
    var d = earthRadius * c; 

    return d; 
} 

目前我的測試是這樣的:

[TestMethod] 
public void GeoPoint_GreatCircleDistanceInKm_IsCorrect() 
{ 
    // arrange 
    var startPoint = new GeoPoint(0, 45, 90); // id, lat, long 
    var endPoint1 = new GeoPoint(0, 45, 90); 
    var endPoint2 = new GeoPoint(0, 0, 0); 

    // act 
    var greatCircleDistanceZero = startPoint.GreatCircleDistanceInKm(endPoint1); 
    var greatCircleDistanceBig = startPoint.GreatCircleDistanceInKm(endPoint2); 

    // assert 
    Assert.AreEqual(0, greatCircleDistanceZero); 
    Assert.AreEqual(10007.543398010288, greatCircleDistanceBig); 
} 

但這似乎錯了,我我先找到答案然後再對它進行測試。這種方法應該如何進行測試?我是否應該通過算法/計算並嘗試瞭解它是如何工作的,以便能夠得出確切的值?

澄清: 我的問題是這是進行這種事情的測試正確的方法,即。我的測試是否應該綁定到實際的實現上(因爲正如你所看到的,我正在使用細粒度的期望值)還是應該以某種方式更通用?

回答

1

您可以使用Assert.AreEqual(double expected, double actual, double delta)。您應該使用足夠小的增量(例如0.00000001)。這裏不推薦使用double.Epsilon。

從MSDN:

由於小量限定正值其範圍是接近零的最小表達,兩個類似的值之間的差值的幅度必須大於小量更大。通常情況下,它比Epsilon大很多倍。因此,我們建議您在比較Double值的相等性時不要使用Epsilon。

對於其他問題:是的,這種方法應該測試。但是,在您檢查算法實現之後編寫測試不是一個好主意,因爲它可能會被錯誤地執行。你需要一個整體的想法,例如該方法應該做什麼(在你的情況下計算greate圓距離)。現在您可以通過指定輸入和預期輸出來指定測試用例。您可以從其他來源檢索預期的輸出(例如手動計算)。

有一點說明:TDD測試用例通常在寫入實際代碼之前指定。所以沒有算法可以通過並找出它的工作原理。

+0

東西是根據所使用的earthRadius計算不同,因特網上的一些算法使用不同的值,即。這一個http://www.daftlogic.com/projects-google-maps-distance-calculator.htm,它給出了10020.584的距離。手工操作也是一種痛苦,因此是衆所周知的C&P代碼。 – sprocket12 2014-12-19 12:34:16

+0

我知道你的意思。我認爲你有兩個選擇。您可以「指定」必須使用具體半徑(例如6371)進行計算,並假設您已使用此值進行測試。所以,你可以選擇你認爲的差異很小。或者你可以計算(例如用Wolfram Alpha)儘可能小的距離和最長的距離。現在你可以指定你的測試用例,說明你的函數的距離必須在這兩個距離之間。 – 2014-12-22 07:23:44

0

也許

Assert.IsTrue(Math.Abs(greatCircleDistanceZero - 0) < Double.Epsilon); 
Assert.IsTrue(Math.Abs(greatCircleDistanceBig - 10007.543398010288) < Double.Epsilon); 
+1

謝謝您的回答,不過我一般指的是一個好主意,以測試對這種固定值是精確到12位小數,或是否有可能在一個更通用的方法來測試。 – sprocket12 2014-12-19 12:10:15

0

下表顯示了赤道上兩點之間的距離。隨着緯度從極點移動,NS距離恆定,但EW距離減小。當我假定使用大圓距離時,結果中的任何精度都大於2位小數是多餘的。

0 decimal places 1.0 = 111.32 km 
1 decimal places 0.1 = 11.132 km 
2 decimal places 0.01 = 1.1132 km 
3 decimal places 0.001 = 111.32 m 
4 decimal places 0.0001 = 11.132 m 
5 decimal places 0.00001 = 1.1132 m