مقارنة المشكلات في dunit checkequals مع قيم حقل العملة

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 يأخذ ذلك في الاعتبار.

نصائح أخرى

أرى أن هناك فقط checkequals () للقيم الممتدة في مصادر Delphi 2007 Dunit. لكن يمكنك استخدام هذا:

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

وإعطاء دلتا مناسبة لقيم العملة.

واجهت نفس المشكلة. يبدو أن بعض DLLs تعدل كلمة تحكم FPU (معالج). هذا ما يفسر سبب عدم حدوث الخطأ دائمًا. يمكن أن يظهر فجأة عند إضافة بعض الاختبارات الجديدة ، التي تستخدم وحدات أخرى من جناح الاختبار السابق. أو إذا قام تحديث البرنامج بتثبيت DLLs السيئة. لقد كتبت عن مدونتي:

لقد وجدت أيضًا أن 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