Сравнение проблем в DUnit CheckEquals со значениями поля Currency

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

  •  20-08-2019
  •  | 
  •  

Вопрос

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

Пример:

CheckEquals(16.65, SomeCurrencyFieldValue);

Повышает:

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

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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;

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

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

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual;
CheckEquals(0.011,0.01,0.009,'will pass');
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top