Write tests for CSV export

pull/77/merge
Alinson S. Xavier 10 years ago
parent 2dfbcfcdb0
commit 1120f56dd4

@ -29,6 +29,9 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.StringWriter;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.isoron.uhabits.models.Checkmark.CHECKED_EXPLICITLY; import static org.isoron.uhabits.models.Checkmark.CHECKED_EXPLICITLY;
@ -140,6 +143,27 @@ public class CheckmarkListTest
assertThat(nonDailyHabit.checkmarks.getTodayValue(), equalTo(UNCHECKED)); assertThat(nonDailyHabit.checkmarks.getTodayValue(), equalTo(UNCHECKED));
} }
@Test
public void writeCSV() throws IOException
{
String expectedCSV =
"2015-01-16,2\n" +
"2015-01-17,2\n" +
"2015-01-18,1\n" +
"2015-01-19,0\n" +
"2015-01-20,2\n" +
"2015-01-21,2\n" +
"2015-01-22,2\n" +
"2015-01-23,1\n" +
"2015-01-24,0\n" +
"2015-01-25,2\n";
StringWriter writer = new StringWriter();
nonDailyHabit.checkmarks.writeCSV(writer);
assertThat(writer.toString(), equalTo(expectedCSV));
}
private void travelInTime(int days) private void travelInTime(int days)
{ {
DateHelper.setFixedLocalTime(HabitFixtures.FIXED_LOCAL_TIME + DateHelper.setFixedLocalTime(HabitFixtures.FIXED_LOCAL_TIME +

@ -19,6 +19,7 @@
package org.isoron.uhabits.unit.models; package org.isoron.uhabits.unit.models;
import org.isoron.uhabits.helpers.ColorHelper;
import org.isoron.uhabits.helpers.DateHelper; import org.isoron.uhabits.helpers.DateHelper;
import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.Habit;
@ -31,6 +32,8 @@ public class HabitFixtures
public static Habit createNonDailyHabit() public static Habit createNonDailyHabit()
{ {
Habit habit = new Habit(); Habit habit = new Habit();
habit.name = "Wake up early";
habit.description = "Did you wake up before 6am?";
habit.freqNum = 2; habit.freqNum = 2;
habit.freqDen = 3; habit.freqDen = 3;
habit.save(); habit.save();
@ -48,6 +51,9 @@ public class HabitFixtures
public static Habit createEmptyHabit() public static Habit createEmptyHabit()
{ {
Habit habit = new Habit(); Habit habit = new Habit();
habit.name = "Meditate";
habit.description = "Did you meditate this morning?";
habit.color = ColorHelper.palette[3];
habit.freqNum = 1; habit.freqNum = 1;
habit.freqDen = 1; habit.freqDen = 1;
habit.save(); habit.save();

@ -23,12 +23,15 @@ import android.graphics.Color;
import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import org.hamcrest.MatcherAssert;
import org.isoron.uhabits.helpers.DateHelper; import org.isoron.uhabits.helpers.DateHelper;
import org.isoron.uhabits.models.Habit; import org.isoron.uhabits.models.Habit;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.StringWriter;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -353,4 +356,21 @@ public class HabitTest
h.clearReminder(); h.clearReminder();
assertThat(h.hasReminder(), is(false)); assertThat(h.hasReminder(), is(false));
} }
@Test
public void writeCSV() throws IOException
{
HabitFixtures.createEmptyHabit();
HabitFixtures.createNonDailyHabit();
String expectedCSV =
"Name,Description,NumRepetitions,Interval,Color\n" +
"Meditate,Did you meditate this morning?,1,1,#AFB42B\n" +
"Wake up early,Did you wake up before 6am?,2,3,#00897B\n";
StringWriter writer = new StringWriter();
Habit.writeCSV(Habit.getAll(true), writer);
MatcherAssert.assertThat(writer.toString(), equalTo(expectedCSV));
}
} }

@ -31,6 +31,9 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.StringWriter;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
@ -130,6 +133,30 @@ public class ScoreListTest
assertThat(actualValues, equalTo(expectedValues)); assertThat(actualValues, equalTo(expectedValues));
} }
@Test
public void writeCSV() throws IOException
{
HabitFixtures.purgeHabits();
Habit habit = HabitFixtures.createNonDailyHabit();
String expectedCSV =
"2015-01-16,0.0519\n" +
"2015-01-17,0.1021\n" +
"2015-01-18,0.0986\n" +
"2015-01-19,0.0952\n" +
"2015-01-20,0.1439\n" +
"2015-01-21,0.1909\n" +
"2015-01-22,0.2364\n" +
"2015-01-23,0.2283\n" +
"2015-01-24,0.2205\n" +
"2015-01-25,0.2649\n";
StringWriter writer = new StringWriter();
habit.scores.writeCSV(writer);
assertThat(writer.toString(), equalTo(expectedCSV));
}
private void toggleRepetitions(final int from, final int to) private void toggleRepetitions(final int from, final int to)
{ {
DatabaseHelper.executeAsTransaction(new DatabaseHelper.Command() DatabaseHelper.executeAsTransaction(new DatabaseHelper.Command()

@ -22,18 +22,13 @@ package org.isoron.uhabits.unit.models;
import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import org.isoron.uhabits.models.Checkmark;
import org.isoron.uhabits.models.Score;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import org.isoron.uhabits.models.Score;
import org.isoron.uhabits.models.Checkmark;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest

@ -76,6 +76,7 @@ public class CheckmarkList
public int[] getValues(long fromTimestamp, long toTimestamp) public int[] getValues(long fromTimestamp, long toTimestamp)
{ {
compute(fromTimestamp, toTimestamp); compute(fromTimestamp, toTimestamp);
if(fromTimestamp > toTimestamp) return new int[0]; if(fromTimestamp > toTimestamp) return new int[0];
String query = "select value, timestamp from Checkmarks where " + String query = "select value, timestamp from Checkmarks where " +
@ -127,6 +128,21 @@ public class CheckmarkList
return getValues(fromTimestamp, toTimestamp); return getValues(fromTimestamp, toTimestamp);
} }
/**
* Computes and stores one checkmark for each day, since the first repetition until today.
* Days that already have a corresponding checkmark are skipped.
*/
protected void computeAll()
{
Repetition oldestRep = habit.repetitions.getOldest();
if(oldestRep == null) return;
Long fromTimestamp = oldestRep.timestamp;
Long toTimestamp = DateHelper.getStartOfToday();
compute(fromTimestamp, toTimestamp);
}
/** /**
* Computes and stores one checkmark for each day that falls inside the specified interval of * Computes and stores one checkmark for each day that falls inside the specified interval of
* time. Days that already have a corresponding checkmark are skipped. * time. Days that already have a corresponding checkmark are skipped.
@ -234,8 +250,18 @@ public class CheckmarkList
else return Checkmark.UNCHECKED; else return Checkmark.UNCHECKED;
} }
/**
* Writes the entire list of checkmarks to the given writer, in CSV format. There is one
* line for each checkmark. Each line contains two fields: timestamp and value.
*
* @param out the writer where the CSV will be output
* @throws IOException in case write operations fail
*/
public void writeCSV(Writer out) throws IOException public void writeCSV(Writer out) throws IOException
{ {
computeAll();
SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat(); SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat();
String query = "select timestamp, value from checkmarks where habit = ? order by timestamp"; String query = "select timestamp, value from checkmarks where habit = ? order by timestamp";
@ -255,5 +281,6 @@ public class CheckmarkList
} while(cursor.moveToNext()); } while(cursor.moveToNext());
cursor.close(); cursor.close();
out.close();
} }
} }

@ -20,7 +20,6 @@
package org.isoron.uhabits.models; package org.isoron.uhabits.models;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
@ -34,16 +33,13 @@ import com.activeandroid.query.From;
import com.activeandroid.query.Select; import com.activeandroid.query.Select;
import com.activeandroid.query.Update; import com.activeandroid.query.Update;
import com.activeandroid.util.SQLiteUtils; import com.activeandroid.util.SQLiteUtils;
import com.opencsv.CSVReader;
import com.opencsv.CSVWriter; import com.opencsv.CSVWriter;
import org.isoron.uhabits.helpers.ColorHelper; import org.isoron.uhabits.helpers.ColorHelper;
import org.isoron.uhabits.helpers.DateHelper; import org.isoron.uhabits.helpers.DateHelper;
import java.io.IOException; import java.io.IOException;
import java.io.Reader;
import java.io.Writer; import java.io.Writer;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@ -478,9 +474,18 @@ public class Habit extends Model
reminderDays = DateHelper.ALL_WEEK_DAYS; reminderDays = DateHelper.ALL_WEEK_DAYS;
} }
/**
* Writes the list of habits to the given writer, in CSV format. There is one line for each
* habit, containing the fields name, description, frequency numerator, frequency denominator
* and color. The color is written in HTML format (#000000).
*
* @param habits the list of habits to write
* @param out the writer that will receive the result
* @throws IOException if write operations fail
*/
public static void writeCSV(List<Habit> habits, Writer out) throws IOException public static void writeCSV(List<Habit> habits, Writer out) throws IOException
{ {
String header[] = { "Name", "Description", "FrequencyNumerator", "FrequencyDenominator", "Color" }; String header[] = { "Name", "Description", "NumRepetitions", "Interval", "Color" };
CSVWriter csv = new CSVWriter(out); CSVWriter csv = new CSVWriter(out);
csv.writeNext(header, false); csv.writeNext(header, false);
@ -494,24 +499,4 @@ public class Habit extends Model
csv.close(); csv.close();
} }
public List<Habit> parseCSV(Reader in)
{
CSVReader csv = new CSVReader(in);
List<Habit> habits = new LinkedList<>();
for(String cols[] : csv)
{
Habit habit = new Habit();
habit.name = cols[0];
habit.description = cols[1];
habit.freqNum = Integer.parseInt(cols[2]);
habit.freqDen = Integer.parseInt(cols[3]);
habit.color = Color.parseColor(cols[4]);
habits.add(habit);
}
return habits;
}
} }

@ -99,6 +99,19 @@ public class ScoreList
.execute(); .execute();
} }
/**
* Computes and saves the scores that are missing since the first repetition of the habit.
*/
private void computeAll()
{
Repetition oldestRep = habit.repetitions.getOldest();
if(oldestRep == null) return;
long fromTimestamp = oldestRep.timestamp;
long toTimestamp = DateHelper.getStartOfToday();
compute(fromTimestamp, toTimestamp);
}
/** /**
* Computes and saves the scores that are missing inside a given time interval. Scores that * Computes and saves the scores that are missing inside a given time interval. Scores that
* have already been computed are skipped, therefore there is no harm in calling this function * have already been computed are skipped, therefore there is no harm in calling this function
@ -285,6 +298,8 @@ public class ScoreList
public void writeCSV(Writer out) throws IOException public void writeCSV(Writer out) throws IOException
{ {
computeAll();
SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat(); SimpleDateFormat dateFormat = DateHelper.getCSVDateFormat();
String query = "select timestamp, score from score where habit = ? order by timestamp"; String query = "select timestamp, score from score where habit = ? order by timestamp";
@ -298,11 +313,12 @@ public class ScoreList
do do
{ {
String timestamp = dateFormat.format(new Date(cursor.getLong(0))); String timestamp = dateFormat.format(new Date(cursor.getLong(0)));
String score = String.format("%.2f", ((float) cursor.getInt(1)) / Score.MAX_VALUE); String score = String.format("%.4f", ((float) cursor.getInt(1)) / Score.MAX_VALUE);
out.write(String.format("%s,%s\n", timestamp, score)); out.write(String.format("%s,%s\n", timestamp, score));
} while(cursor.moveToNext()); } while(cursor.moveToNext());
cursor.close(); cursor.close();
out.close();
} }
} }

Loading…
Cancel
Save