Skip to main content

Testing con operaciones de número flotante: eventos astronómicos

Introducción

En computación, los cálculos numéricos, especialmente los que implican flotantes, pueden ser propensos a pequeñas imprecisiones. Esto se debe a la forma en que las computadoras manejan la aritmética de punto flotante. Las imprecisiones pueden acumularse en cálculos complejos, lo que puede llevar a resultados ligeramente fuera de lo esperado.

En el caso de una aplicación que estaba haciendo de repente unos test me comenzaron a fallar justo cuando habia realizado unos cambios. Pero menos mal que me fije en los datos del fallo del test.

Era un simple segundo en la aserción de un datao astronomico calculado con el método de PHP date_sun_info

   FAILED  Tests\Unit\Observers\CommandCenterObserverTest > create command center fire observer and save astro sun info                                      
  Failed asserting that a row in the table [command_centers] matches the attributes {
    "sunrise": "2022-11-30 07:14:32",
    "sunset": "2022-11-30 16:46:11"
}.

Found similar results: [
    {
        "sunrise": "2022-11-30 07:14:32",
        "sunset": "2022-11-30 16:46:10"  << Fallo de un segundo
    }
].

Solución

En este tipo de casos en el que trabajamos con cuestiones que no requieren una exactitud matemática al más puro estilo de C++, podemos modificar nuestro test.

Parte del test original

$this->assertDatabaseHas('command_centers', [
    'sunrise' => '2022-11-30 07:14:32',
    'sunset' => '2022-11-30 16:46:11',
]);

Parte modificada del test

$expectedSunrise = Carbon::createFromFormat('Y-m-d H:i:s', '2022-11-30 07:14:32');
$actualSunrise = Carbon::createFromFormat('Y-m-d H:i:s', $commandCenter->sunrise->format('Y-m-d H:i:s'));

$this->assertLessThanOrEqual(
    1, // seconds of allowable difference
    $expectedSunrise->diffInSeconds($actualSunrise),
    'Sunrise time difference is more than 1 second'
);

$expectedSunset = Carbon::createFromFormat('Y-m-d H:i:s', '2022-11-30 16:46:11');
$actualSunset = Carbon::createFromFormat('Y-m-d H:i:s', $commandCenter->sunset->format('Y-m-d H:i:s'));

$this->assertLessThanOrEqual(
    1, // seconds of allowable difference
    $expectedSunset->diffInSeconds($actualSunset),
    'Sunset time difference is more than 1 second'
);
Aviso

Esta documentación y su contenido, no implica que funcione en tu caso o determinados casos. También implica que tienes conocimientos sobre lo que trata, y que en cualquier caso tienes copias de seguridad. El contenido el contenido se entrega, tal y como está, sin que ello implique ningún obligación ni responsabilidad por parte de Castris

Si necesitas soporte profesional puedes contratar con Castris soporte profesional.