Comparaison des problèmes dans les contrôles DUnit CheckEquals avec les valeurs du champ monétaire

StackOverflow https://stackoverflow.com/questions/488746

  •  20-08-2019
  •  | 
  •  

Question

Je compare certaines valeurs de devise dans DUnit, mais cela ne fonctionne pas du tout sur ma machine (fonctionne sur d'autres, mais pas sur la mienne).

Un exemple:

CheckEquals(16.65, SomeCurrencyFieldValue);

Élève:

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

si la comparaison suivante fonctionne, alors:

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

La question qui se pose est la suivante: pourquoi la comparaison ne fonctionne-t-elle pas lorsque je passe directement la valeur à la méthode CheckEquals?

Était-ce utile?

La solution

Le problème est lié à la manière dont Currency les valeurs sont converties en Extended valeurs au moment de l'exécution par rapport au mode de conversion des littéraux à virgule flottante en CheckEquals valeurs au moment de la compilation. Si la conversion n’est pas la même dans les deux cas, les valeurs transmises à Double peuvent ne pas être équivalentes.

Il serait utile de vérifier dans la fenêtre de la CPU du débogueur si l'une ou l'autre des valeurs passe par une valeur <=> intermédiaire avant de se rendre à <=> en préparation de l'appel de fonction. Une conversion supplémentaire affecterait la valeur exacte du résultat.

Une autre chose à considérer est que 16.65 n'est pas représentable exactement comme une <=> valeur, mais est exactement comme une <=> valeur. Bien que <=> soit classé en tant que type à virgule flottante, il s’agit en réalité d’un nombre entier 64 bits mis à l’échelle en points fixes. C’est probablement une raison pour demander une <=> surcharge supplémentaire dans DUnit tenant compte de cela.

Autres conseils

Je vois qu'il n'y a que CheckEquals () pour les valeurs étendues dans les sources Delphi 2007 dUnit. Mais vous pouvez utiliser celui-ci:

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

et donnez un delta approprié aux valeurs monétaires.

J'ai rencontré le même problème. Il semble que certaines DLL modifient un mot de contrôle FPU (processeur). Cela explique pourquoi l'erreur ne se produit pas toujours. Il peut apparaître soudainement lorsque de nouveaux tests, qui utilisent d'autres unités que la suite de tests précédente, sont ajoutés. Ou si une mise à jour logicielle installe de mauvaises DLL. J'ai écrit sur mon blog:

J'ai également constaté que Delphi contient une fonction SafeLoadLibrary, qui restaure le mot de contrôle.

Cela explique également pourquoi la question initiale indique que le problème dépend de la machine.

voici une solution suggérée:

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;

Je connais sa mauvaise implémentation, mais c'est juste une idée, que j'aime mieux que & "; delta &"; et beaucoup plus facile à utiliser.

Dans la version actuelle de dunit, vous pouvez utiliser

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual;
CheckEquals(0.011,0.01,0.009,'will pass');
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top