2009-01-28 10 views
7

Ich vergleiche einige Währungswerte in DUnit, aber es funktioniert überhaupt nicht auf meinem Computer (Arbeit an anderen, aber nicht an meinem).Vergleichen von Problemen in DUnit CheckEquals mit Währungsfeldwerten

Ein Beispiel:

CheckEquals(16.65, SomeCurrencyFieldValue); 

Löst:

expected: <16,65> but was: <16,65> 

, wenn die nach dem Vergleich tun dann funktioniert:

var 
    Temp: Currency; 
begin 
    Temp := 16.65; 
    CheckEquals(Temp, SomeCurrencyFieldValue); 

Die Frage ist: Warum der Vergleich nicht der Fall ist arbeite, wenn ich den Wert direkt an die CheckEquals-Methode übergebe?

Antwort

5

Das Problem hat damit zu tun, wie Currency Werte Extended Werte zur Laufzeit konvertiert werden im Vergleich zu, wie Gleitpunktliterale zu Extended Werten bei der Kompilierung konvertiert werden. Wenn die Konvertierung in beiden Fällen nicht identisch ist, können die Werte, die an CheckEquals übergeben werden, nicht gleichwertig sein.

Es lohnt sich, im CPU-Fenster des Debuggers nachzusehen, ob einer der Werte einen Zwischenwert Double auf seinem Weg zu Extended als Vorbereitung für den Funktionsaufruf durchläuft. Eine zusätzliche Konvertierung würde den genauen Wert des Ergebnisses beeinflussen.

Eine andere Sache zu prüfen ist, dass 16,65 nicht genau darstellbar als Extended Wert, aber es ist darstellbare genau als Currency Wert. Obwohl Currency als Floating-Point-Typ klassifiziert ist, handelt es sich tatsächlich um eine 64-Bit-Ganzzahl mit festem Punkt. Das ist wahrscheinlich ein Grund dafür, eine zusätzliche CheckEquals Überlast in DUnit anzufordern, die das berücksichtigt.

+0

Warum funktioniert es auf einigen anderen Maschinen? – mjn

1

Ich sehe, dass es nur checkEquals() für erweiterte Werte in den Delphi 2007 dUnit Quellen gibt. Aber Sie könnten diesen verwenden:

procedure CheckEquals(expected, actual: extended; delta: extended; 
    msg: string = ''); overload; virtual; 

und geben Sie ein richtiges Delta für Währungswerte.

+0

Nö, Ungültige Typumwandlung verwenden. –

1

Ich stieß auf das gleiche Problem. Es sieht so aus, als ob einige DLLs ein FPU (Prozessor) -Steuerwort modifizieren. Dies erklärt, warum der Fehler nicht immer auftritt. Es kann plötzlich erscheinen, wenn neue Tests hinzugefügt werden, die andere Einheiten als die vorherige Testsuite verwenden. Oder wenn ein Softwareupdate fehlerhafte DLLs installiert. Ich habe auf meinem Blog darüber geschrieben:

Ich fand auch, dass Delphi eine SafeLoadLibrary Funktion enthält, die das Steuerwort wieder her.

Dies erklärt auch, warum die ursprüngliche Frage erwähnt, dass das Problem maschinenabhängig ist.

-1

hier ist eine vorgeschlagene Lösung:

procedure CheckEquals(expected, actual: double; Precision:integer; msg:string ='');overload;virtual; 

...

procedure TAbstractTest.CheckEquals(expected, actual: double; 
    Precision: integer; msg: string); 
var 
    I: Integer; 
begin 
    FCheckCalled := true; 
    for I := 0 to Precision do begin 
    Expected := Expected * 10; 
    Actual := Actual * 10; 
    end; 
    if Round(Expected) <> Round(Actual) then 
    FailNotEquals(IntToStr(Round(Expected)), IntToStr(Round(Actual)), msg, CallerAddr); 
end; 

Ich weiß, seine schlechte Umsetzung, aber nur eine Idee, dass mir besser gefällt dann „Delta“ und viel einfacher zu bedienen.

In der aktuellen Version von dunit können Sie

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual; 
CheckEquals(0.011,0.01,0.009,'will pass');