Как сравнить строковое представление двойников, если оно заканчивается.Ноль ноль
В настоящее время я пишу тестовые случаи для ContentProvider в моем приложении (которое является приложением для записи чековой книжки), и у меня происходит сбой теста, когда он сравнивает двойные значения. Лучший способ проиллюстрировать это-с помощью кода. У меня есть эта функция, которая возвращает ContentValues для объекта account, который будет вставлен в базу данных:
private ContentValues getAccountContentValues(){
String testName = "Capital One";
double testStartingBalance = 3000.00;
ContentValues accountValues = new ContentValues();
accountValues.put(AccountEntry.COLUMN_NAME, testName);
accountValues.put(AccountEntry.COLUMN_BALANCE, testStartingBalance);
return accountValues;
}
Внутри функции testInsertReadProvider()
у меня есть следующий код, чтобы вставить эту учетную запись:
// Get Account values and write them
ContentValues accountValues = getAccountContentValues();
Uri accountInsertUri =
mContext.getContentResolver().insert(AccountEntry.CONTENT_URI, accountValues);
long accountRowId = ContentUris.parseId(accountInsertUri);
// Verify we got a row back
assertTrue(accountRowId > 0);
// A cursor is the primary interface to the query results
Cursor cursor = mContext.getContentResolver().query(
AccountEntry.CONTENT_URI, // Table name
null, // columns to be returned. Null returns all columns
null, // Columns for where clause
null, // Values for where clause
null // Sort order
);
// Validate the information read from the database.
validateCursor(cursor, accountValues);
cursor.close();
Функция validate cursor принимает курсор и ContentValues и циклы через них, используя карту для сравнения каждого значения. Это стратегия, которую я узнал из учебника Udacity по созданию приложений для Android, так что, возможно, есть лучший способ сравнить их, а не как строки, но это выглядит так:
void validateCursor(Cursor valueCursor, ContentValues expectedValues){
assertTrue(valueCursor.moveToFirst());
Set<Map.Entry<String, Object>> valueSet = expectedValues.valueSet();
for(Map.Entry<String, Object> entry : valueSet){
String columnName = entry.getKey();
int idx = valueCursor.getColumnIndex(columnName);
assertFalse(idx == -1);
String expectedValue = entry.getValue().toString();
assertEquals(expectedValue, valueCursor.getString(idx));
}
valueCursor.close();
}
Тест не выполняется, когда вызывается строка assertEquals()
, и я получаю следующее сообщение об ошибке:
Джунит.рамки.ComparisonFailure: ожидается: но было:
Похоже, что указатель.метод getString() усекает десятичные разряды, если они равны 0. Если я попробую этот тест, используя значение 3000.01, он работает нормально. Является ли SQLite ответственным за удаление ненужных нулей? Могу ли я изменить assertEquals()
таким образом, чтобы эти два значения обрабатывались одинаково?
2 ответа:
Если вы действительно хотите сравнить строки, то вам придется немного взломать его, но ниже есть альтернатива.
Во-первых, вот код TL;DR;:
for(Map.Entry<String, Object> entry : valueSet){ String columnName = entry.getKey(); int idx = valueCursor.getColumnIndex(columnName); assertFalse(idx == -1); String expectedValue = entry.getValue().toString(); if((Cursor.FIELD_TYPE_FLOAT == valueCursor.getType(idx)) && valueCursor.getDouble(idx) % 1 == 0){ assertEquals(expectedValue, valueCursor.getString(idx) + ".0"); } else { assertEquals(expectedValue, valueCursor.getString(idx)); } }
Вероятно, происходит то, что каждый экземпляр вашего
double
в конце проецируется наString
другимtoString()
методом. Вот что вызывает нарушения.Вы можете либо взломать его, как я описал выше, либо выполнить сравнение в операторе switch, специально разработанном для каждый тип (ИМХО лучшее решение) .
Вот переключатель версия:
for(Map.Entry<String, Object> entry : valueSet){ String columnName = entry.getKey(); int idx = valueCursor.getColumnIndex(columnName); assertFalse(idx == -1); switch(valueCursor.getType(idx)) { case Cursor.FIELD_TYPE_FLOAT: assertEquals(entry.getValue(), valueCursor.getDouble(idx)); break; case Cursor.FIELD_TYPE_INTEGER: //assertEquals(entry.getValue(), valueCursor.getInt(idx)); // didn't work //assertTrue((new Integer((int)entry.getValue())).equals(valueCursor.getInt(idx))); assertEquals(Integer.parseInt(entry.getValue().toString()), valueCursor.getInt(idx)); case Cursor.FIELD_TYPE_STRING: assertEquals(entry.getValue(), valueCursor.getString(idx)); break; default: assertEquals(entry.getValue().toString(), valueCursor.getString(idx)); } }
Вы должны перенести их в двойники, используя
double d1 = Double.parseDouble(text) double d2 = Double.parseDouble(text2)
Проделайте то же самое для второй строки и сравните результаты. Вы также можете использовать abs, чтобы убедиться, что нет никакой разницы из-за представления:
assertTrue(Math.abs(d1 -d2) < 0.00001);
Правка:
Я бы выбрал что-то вроде этого:
try { double d1 = Double.parseDouble(text); double d2 = Double.parseDouble(text2); assertTrue(Math.abs(d1-d2) < 0.00001); }catch(NumberFormatException e) { assertEquals(text, text2); }