Domanda

Sto confrontando alcuni valori di valuta in DUnit ma non funziona affatto sul mio computer (funziona su altri, ma non sul mio).

Un esempio:

CheckEquals(16.65, SomeCurrencyFieldValue);

Aumenta:

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

se procede come segue il confronto funziona:

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

La domanda è: perché il confronto non funziona quando passo il valore direttamente al metodo CheckEquals?

È stato utile?

Soluzione

Il problema riguarda il modo in cui Currency i valori vengono convertiti in Extended valori in fase di esecuzione rispetto al modo in cui i valori letterali in virgola mobile vengono convertiti in CheckEquals valori in fase di compilazione. Se la conversione non è la stessa in entrambi i casi, i valori passati a Double potrebbero non essere uguali.

Vale la pena verificare nella finestra della CPU del debugger se uno dei valori passa attraverso un valore <=> intermedio sulla strada per <=> in preparazione alla chiamata di funzione. Una conversione aggiuntiva influirebbe sul valore esatto del risultato.

Un'altra cosa da considerare è che 16.65 non è rappresentabile esattamente come <=> valore, ma è rappresentabile esattamente come <=> valore. Sebbene <=> sia classificato come tipo a virgola mobile, in realtà è un intero a 64 bit in scala a virgola fissa. Questo è probabilmente un motivo per richiedere un ulteriore <=> sovraccarico in DUnit che ne tenga conto.

Altri suggerimenti

Vedo che esiste solo CheckEquals () per i valori estesi nelle origini dUnit di Delphi 2007. Ma potresti usare questo:

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

e indica un delta adeguato per i valori di valuta.

Ho riscontrato lo stesso problema. Sembra che alcune DLL modifichino una parola di controllo FPU (processore). Questo spiega perché l'errore non si verifica sempre. Può apparire improvvisamente quando vengono aggiunti alcuni nuovi test, che utilizzano unità diverse dalla precedente suite di test. O se un aggiornamento software installa DLL errate. Ho scritto sul mio blog:

Ho anche scoperto che Delphi contiene una funzione SafeLoadLibrary, che ripristina la parola di controllo.

Questo spiega anche perché la domanda originale menziona che il problema dipende dalla macchina.

ecco una soluzione suggerita:

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;

Conosco la sua cattiva implementazione, ma solo un'idea, che mi piace meglio di " delta " e molto più facile da usare.

Nella versione corrente di dunit puoi usare

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual;
CheckEquals(0.011,0.01,0.009,'will pass');
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top