How to compare String representations of doubles if it ends in .00
I am currently writing test cases for a ContentProvider in my application (which is a checkbook recording app) and I am having a test fail when it is comparing double values. The best way to illustrate this is with code. I have this function that returns ContentValues for an account object to be inserted into the database:
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;
}
Inside a function testInsertReadProvider()
I have the following code, to insert that account:
// 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();
The validate cursor function takes a cursor and a ContentValues and loops through them using a map to compare each value. This is a strategy I learned from following a Udacity tutorial on creating Android applications, so maybe there is a better way to compare them instead of as strings, but it looks like this:
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();
}
The test is failing when the assertEquals()
line is called, and I get the following error message:
junit.framework.ComparisonFailure: expected:<3000[.0]> but was:<3000[]>
It looks like the cursor.getString() method is truncating the decimal places if they are equal to 0. If I try this test using a value of 3000.01 it works fine. Is SQLite responsible for dropping the unnecessary zeroes? Can I change the assertEquals()
in some way so that those two values are treated the same?
If you really feel like comparing strings, than you will have to hack it a little bit, but there is an alternative below.
First, here's the TL;DR; code:
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));
}
}
What is probably happening is that each instance of your double
is at the end being projected to String
by a different toString()
method. That's what causing the irregularities.
You can either hack it as I outlined above or do the comparison in a switch statement specifically designed for each type (IMHO a better solution).
Here is the Switch version:
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));
}
}
You should transfer them to doubles using
double d1 = Double.parseDouble(text) double d2 = Double.parseDouble(text2)
Do the same for second string and compare results. You can also use abs to be sure there is no difference because of representation:
assertTrue(Math.abs(d1 -d2) < 0.00001);
EDIT:
I would go for something like this:
try
{
double d1 = Double.parseDouble(text);
double d2 = Double.parseDouble(text2);
assertTrue(Math.abs(d1-d2) < 0.00001);
}catch(NumberFormatException e)
{
assertEquals(text, text2);
}
链接地址: http://www.djcxy.com/p/84538.html
上一篇: 替换不在两个特定单词之间的字符串