Модульное тестирование с Laravel assertDatabaseHas и плавающим столбцом - PullRequest
1 голос
/ 05 февраля 2020

Выполняю некоторые тесты в моем приложении Laravel, и у меня периодически возникают сбои из-за того, что один из столбцов моей базы данных определен как FLOAT. При запуске теста с assertDatabaseHas() иногда происходит сбой из-за неопределенности с плавающей запятой.

<?php

namespace Test\Unit;

use App\Foo;

class MyModelTest extends TestCase
{
    public function testFooCanBar(): void
    {
        $stringvalue = "baz";
        $floatvalue = 234.281;
        $data = [
            "name" => $stringvalue,
            "data" => $floatvalue,
        ];
        Foo::bar($stringvalue, $floatvalue);
        $this->assertDatabaseHas("foos", $data);
    }
}

Иногда результат:

Failed asserting that a row in the table [foos] matches the attributes {
    "name": "baz",
    "data": 234.281
}.

Found similar results: [
    {
        "name": "baz",
        "data": 234.280999999999999995
    }
]

Я могу вспомнить несколько способы обойти это (изменить столбец на INT и умножить на 10 ^ x или просто удалить столбец из сравнения), но мне интересно, есть ли какие-то методы, которые я пропустил, чтобы правильно проверить это. При непосредственном сравнении значений мы можем использовать PHPUnit assertEqualsWithDelta(); Есть ли что-нибудь подобное для проверки базы данных?

1 Ответ

1 голос
/ 06 февраля 2020

В MySQL базах данных (в настоящее время v8) тип данных FLOAT или DOUBLE всегда сохраняется как приблизительное значение:

Типы FLOAT и DOUBLE представляют приблизительные числа c значения данных. MySQL использует четыре байта для значений одинарной точности и восемь байтов для значений двойной точности.

- из: MySQL Тип данных FLOAT и DOUBLE

С другой стороны, тип данных DECIMAL позволяет хранить точные десятичные значения длиной до 65 цифр.

Типы DECIMAL и NUMERIC хранят точные числа c значений данных. Эти типы используются, когда важно сохранить точную точность, например, с денежными данными.

- из: MySQL Ссылка на тип данных DECIMAL

Проблемы с документацией FLOAT (ссылка)

MySQL покрывают проблему с неточными типами данных FLOAT и DOUBLE и показывают возможное решение для использования этих типов с разностными отличиями на уровнях базы данных (полный пример в ссылочной ссылке):

SELECT i, SUM(d1) AS a, SUM(d2) AS b
FROM t1
GROUP BY i
HAVING ABS(a - b) > 0.0001;

Важное примечание : Помните, что FLOAT и DOUBLE также зависят от платформы!

Оператор SELECT, подобный приведенному ниже, может возвращать 0 и -0 или inf и -inf в зависимости от среды выполнения:

CREATE TABLE t1(c1 FLOAT(53,0), c2 FLOAT(53,0));
INSERT INTO t1 VALUES('1e+52','-1e+52');
SELECT * FROM t1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...