Pergunta

Eu estou comparando alguns valores de moeda em DUnit, mas não está funcionando em tudo na minha máquina (trabalho em outros, mas não no meu).

Um exemplo:

CheckEquals(16.65, SomeCurrencyFieldValue);

Levanta:

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

se fazer a seguinte comparação, em seguida, funciona:

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

A questão é:Por que a comparação não funciona quando eu passar o valor direto para o CheckEquals método?

Foi útil?

Solução

O problema tem a ver com a forma como Currency os valores são convertidos para Extended valores em tempo de execução versus como ponto flutuante literais convertido para Extended valores em tempo de compilação.Se a conversão não é o mesmo em ambos os casos, os valores passados para CheckEquals não pode comparar igual.

Seria a pena conferir o depurador na CPU janela se qualquer um dos valores passa por um intermediário Double valor em seu caminho para Extended em preparação para a chamada de função.Um extra de conversão afetaria o valor exato do resultado.

Outra coisa a considerar é que 16.65 não é exatamente representáveis como um Extended valor, mas é representáveis exatamente como um Currency o valor.Apesar de Currency é classificado como um tipo de ponto flutuante, ele é realmente um ponto fixo em escala inteiro de 64 bits.Essa é provavelmente a razão para o pedido de adicional CheckEquals sobrecarga em DUnit que leva em conta.

Outras dicas

Vejo que existem apenas checkequals () para valores estendidos nas fontes Dunit Delphi 2007. Mas você pode usar este:

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

e dê um delta adequado para valores de moeda.

Eu encontrei o mesmo problema. Parece que algumas DLLs modificam uma palavra de controle FPU (processador). Isso explica por que o erro nem sempre ocorre. Pode aparecer repentinamente quando alguns novos testes, que usam outras unidades além do conjunto de testes anteriores, são adicionados. Ou se uma atualização de software instalar DLLs ruins. Eu escrevi sobre no meu blog:

Também descobri que o Delphi contém uma função SafeloAdlibrary, que restaura a palavra de controle.

Isso também explica por que a pergunta original menciona que o problema depende da máquina.

Aqui está uma solução sugerida:

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;

Sei que sua implementação ruim, mas apenas uma idéia, de que gosto mais do que "Delta" e muito mais fácil de usar.

Na versão atual da dunit, você pode usar

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual;
CheckEquals(0.011,0.01,0.009,'will pass');
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top