Сравнение проблем в DUnit CheckEquals со значениями полей валюты - PullRequest
7 голосов
/ 28 января 2009

Я сравниваю некоторые значения валют в DUnit, но он не работает на моем компьютере (работает на других, но не на моем).

Пример:

CheckEquals(16.65, SomeCurrencyFieldValue);

Поднимает:

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

если сделать следующее сравнение, то работает:

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

Вопрос: почему сравнение не работает, когда я передаю значение непосредственно методу CheckEquals?

Ответы [ 4 ]

5 голосов
/ 28 января 2009

Проблема связана с тем, как Currency значения преобразуются в Extended значения во время выполнения, по сравнению с тем, как литералы с плавающей запятой преобразуются в Extended значения во время компиляции. Если преобразование не одинаково в обоих случаях, тогда значения, переданные в CheckEquals, могут не совпадать.

Стоит проверить в окне ЦП отладчика, проходит ли какое-либо из значений промежуточное значение Double на пути к Extended при подготовке к вызову функции. Дополнительное преобразование повлияет на точное значение результата.

Еще одна вещь, которую следует учитывать, - это то, что 16,65 не представляется точно как значение Extended, но является представляемым точно как значение Currency. Хотя Currency классифицируется как тип с плавающей запятой, на самом деле это 64-битное целое число с фиксированной запятой. Вероятно, это является основанием для запроса дополнительной перегрузки CheckEquals в DUnit, которая учитывает это.

1 голос
/ 10 ноября 2010

Я столкнулся с той же проблемой. Похоже, что некоторые библиотеки DLL модифицируют управляющее слово FPU (процессор). Это объясняет, почему ошибка не возникает всегда. Он может появиться внезапно, когда будут добавлены некоторые новые тесты, в которых используются модули, отличные от предыдущего набора тестов. Или, если обновление программного обеспечения устанавливает плохие библиотеки DLL. Я написал в своем блоге:

Я также обнаружил, что Delphi содержит функцию SafeLoadLibrary, которая восстанавливает контрольное слово.

Это также объясняет, почему в первоначальном вопросе упоминается, что проблема зависит от машины.

1 голос
/ 28 января 2009

Я вижу, что в расширенных значениях Delphi 2007 dUnit есть только CheckEquals () для расширенных значений. Но вы можете использовать это:

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

и укажите правильную дельту для валютных значений.

0 голосов
/ 16 июля 2013

Вот предлагаемое решение:

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;

Я знаю, что это плохая реализация, но просто идея, которая мне нравится лучше, чем "delta", и намного проще в использовании.

В текущей версии Dunit вы можете использовать

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