diff --git a/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java b/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java index b412a9726..bbdd7b0cc 100644 --- a/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java +++ b/astrid/src/com/todoroo/astrid/provider/Astrid3ContentProvider.java @@ -192,7 +192,7 @@ public class Astrid3ContentProvider extends ContentProvider { throw new UnsupportedOperationException("Unknown URI " + uri); } - static void setDatabaseOverride(AbstractDatabase override) { + public static void setDatabaseOverride(AbstractDatabase override) { databaseOverride = override; } diff --git a/tests-sync/.classpath b/tests-sync/.classpath index 94408bfa2..bf2584e47 100644 --- a/tests-sync/.classpath +++ b/tests-sync/.classpath @@ -2,8 +2,11 @@ - + + + + diff --git a/tests-sync/AndroidManifest.xml b/tests-sync/AndroidManifest.xml index 115cf9f4f..aa5ec9cb3 100644 --- a/tests-sync/AndroidManifest.xml +++ b/tests-sync/AndroidManifest.xml @@ -1,19 +1,25 @@ + - + package="com.todoroo.astrid.sync.tests" + android:versionCode="1" + android:versionName="1.0"> + - - - - + + + - - \ No newline at end of file + + + + diff --git a/tests-sync/project.properties b/tests-sync/project.properties index 730e911f2..816c46ffb 100644 --- a/tests-sync/project.properties +++ b/tests-sync/project.properties @@ -9,3 +9,5 @@ # Project target. target=android-14 +android.library.reference.1=../api +android.library.reference.2=../facebook/facebook diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksApiTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksApiTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksApiTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksApiTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksDetailExposerTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksDetailExposerTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksDetailExposerTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksDetailExposerTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksIndentActionTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksIndentActionTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksIndentActionTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksIndentActionTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksMetadataServiceTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksMetadataServiceTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksMetadataServiceTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksMetadataServiceTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksNewSyncTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksNewSyncTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksNewSyncTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksNewSyncTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksSyncOnSaveTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksSyncOnSaveTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksSyncOnSaveTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksSyncOnSaveTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksSyncTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksSyncTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksSyncTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksSyncTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksTaskListUpdaterTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksTaskListUpdaterTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksTaskListUpdaterTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksTaskListUpdaterTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksTaskMovingTest.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksTaskMovingTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksTaskMovingTest.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksTaskMovingTest.java diff --git a/tests/src/com/todoroo/astrid/gtasks/GtasksTestPreferenceService.java b/tests-sync/src/com/todoroo/astrid/gtasks/GtasksTestPreferenceService.java similarity index 100% rename from tests/src/com/todoroo/astrid/gtasks/GtasksTestPreferenceService.java rename to tests-sync/src/com/todoroo/astrid/gtasks/GtasksTestPreferenceService.java diff --git a/tests/src/com/todoroo/astrid/producteev/ProducteevSyncTest.java b/tests-sync/src/com/todoroo/astrid/producteev/ProducteevSyncTest.java similarity index 100% rename from tests/src/com/todoroo/astrid/producteev/ProducteevSyncTest.java rename to tests-sync/src/com/todoroo/astrid/producteev/ProducteevSyncTest.java diff --git a/tests-sync/src/com/todoroo/astrid/sync/repeats/AbstractSyncRepeatTests.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/AbstractSyncRepeatTests.java new file mode 100644 index 000000000..ddd08d771 --- /dev/null +++ b/tests-sync/src/com/todoroo/astrid/sync/repeats/AbstractSyncRepeatTests.java @@ -0,0 +1,414 @@ +package com.todoroo.astrid.sync.repeats; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; + +import android.content.Intent; + +import com.google.ical.values.Frequency; +import com.google.ical.values.RRule; +import com.google.ical.values.Weekday; +import com.google.ical.values.WeekdayNum; +import com.timsu.astrid.R; +import com.todoroo.andlib.data.TodorooCursor; +import com.todoroo.andlib.service.Autowired; +import com.todoroo.andlib.sql.Query; +import com.todoroo.andlib.utility.DateUtilities; +import com.todoroo.andlib.utility.Preferences; +import com.todoroo.astrid.api.AstridApiConstants; +import com.todoroo.astrid.dao.MetadataDao; +import com.todoroo.astrid.dao.TaskDao; +import com.todoroo.astrid.dao.TaskDao.TaskCriteria; +import com.todoroo.astrid.data.Task; +import com.todoroo.astrid.repeats.RepeatTaskCompleteListener; +import com.todoroo.astrid.service.StartupService; +import com.todoroo.astrid.test.DatabaseTestCase; +import com.todoroo.astrid.utility.Flags; + +abstract public class AbstractSyncRepeatTests extends DatabaseTestCase { + + @Autowired + protected TaskDao taskDao; + + @Autowired + protected MetadataDao metadataDao; + + @Override + protected void setUp() throws Exception { + super.setUp(); + Preferences.setStringFromInteger(R.string.p_default_urgency_key, 0); + RepeatTaskCompleteListener.setSkipActFmCheck(true); + } + + private void saveAndTriggerRepeatListener(Task task) { + Flags.set(Flags.ACTFM_SUPPRESS_SYNC); + if(task.isSaved()) + taskDao.saveExisting(task); + else + taskDao.createNew(task); + + Intent intent = new Intent(AstridApiConstants.BROADCAST_EVENT_TASK_COMPLETED); + intent.putExtra(AstridApiConstants.EXTRAS_TASK_ID, task.getId()); + new RepeatTaskCompleteListener().onReceive(getContext(), intent); + } + + protected void waitAndSync() { + // Subclasses can override this to insert sync functionality + } + + /** + * @param t + * @param expectedDueDate + */ + protected REMOTE_MODEL assertTaskExistsRemotely(Task t, long expectedDueDate) { + // Subclasses can override this to check the existence of remote objects + return null; + } + + /** + * @param t task + */ + protected void assertTaskCompletedRemotely(Task t) { + // Subclasses can override this to check the status of the corresponding remote task + } + + + /** + * @param remoteModel + */ + protected long setCompletionDate(boolean completeBefore, Task t, + REMOTE_MODEL remoteModel, long dueDate) { + long completionDate; + if (completeBefore) + completionDate = dueDate - DateUtilities.ONE_DAY; + else + completionDate = dueDate + DateUtilities.ONE_DAY; + t.setValue(Task.COMPLETION_DATE, completionDate); + saveAndTriggerRepeatListener(t); + return completionDate; + } + + protected void assertTimesMatch(long expectedTime, long newDueDate) { + assertTrue(String.format("Expected %s, was %s", new Date(expectedTime), new Date(newDueDate)), + Math.abs(expectedTime - newDueDate) < 5000); + } + + /* + * Tests for no sync + */ + + public void testNoRepeat() { + Task t = new Task(); + t.setValue(Task.TITLE, "no repeat"); + taskDao.save(t); + + t.setValue(Task.COMPLETION_DATE, DateUtilities.now()); + saveAndTriggerRepeatListener(t); + + TodorooCursor cursor = taskDao.query(Query.select(Task.ID)); + try { + assertEquals(1, cursor.getCount()); + } finally { + cursor.close(); + } + } + + protected void testRepeating(boolean completeBefore, boolean fromCompletion, + RRule rrule, Frequency frequency, String title) { + for (int i = 0; i < StartupService.INTRO_TASK_SIZE; i++) { // Create startup tasks so sync services don't miss the test tasks + Task temp = new Task(); + temp.setValue(Task.TITLE, "" + i); + taskDao.save(temp); + } + Task t = new Task(); + t.setValue(Task.TITLE, title); + long dueDate = DateUtilities.now() + DateUtilities.ONE_DAY * 3; + dueDate = (dueDate / 1000L) * 1000L; // Strip milliseconds + if (fromCompletion) + t.setFlag(Task.FLAGS, Task.FLAG_REPEAT_AFTER_COMPLETION, true); + + t.setValue(Task.DUE_DATE, dueDate); + + if (rrule == null) { + rrule = new RRule(); + rrule.setFreq(frequency); + int interval = 2; + rrule.setInterval(interval); + } + t.setValue(Task.RECURRENCE, rrule.toIcal()); + taskDao.save(t); + + waitAndSync(); + t = taskDao.fetch(t.getId(), Task.PROPERTIES); // Refetch + REMOTE_MODEL remoteModel = assertTaskExistsRemotely(t, dueDate); + + long completionDate = setCompletionDate(completeBefore, t, remoteModel, dueDate); + + waitAndSync(); + assertTaskCompletedRemotely(t); + + TodorooCursor cursor = taskDao.query(Query.select(Task.PROPERTIES).where(TaskCriteria.notDeleted())); + try { + for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { + Task task = new Task(cursor); + System.err.println("Task: " + task.getValue(Task.TITLE) + ", due: " + task.getValue(Task.DUE_DATE)); + } + assertEquals(StartupService.INTRO_TASK_SIZE + 2, cursor.getCount()); + cursor.moveToFirst(); + for (int i = 0; i < StartupService.INTRO_TASK_SIZE; i++) { + cursor.moveToNext(); + } + t.readFromCursor(cursor); + + assertEquals(title, t.getValue(Task.TITLE)); + assertEquals(dueDate, (long)t.getValue(Task.DUE_DATE)); + assertTrue(t.isCompleted()); + + cursor.moveToNext(); + t.readFromCursor(cursor); + assertEquals(title, t.getValue(Task.TITLE)); + assertFalse(t.isCompleted()); + long newDueDate = t.getValue(Task.DUE_DATE); + assertTrue(t.hasDueTime()); + + long fromDate = (fromCompletion? completionDate : dueDate); + long expectedTime = computeNextDueDateFromDate(fromDate, rrule, fromCompletion); + + assertTaskExistsRemotely(t, expectedTime); + assertTimesMatch(expectedTime, newDueDate); + } finally { + cursor.close(); + } + } + + private long computeWeeklyCaseDueDate(long fromDate, RRule rrule, boolean fromCompletion) { + long result = fromDate; + Frequency frequency = rrule.getFreq(); + assertTrue(frequency.equals(Frequency.WEEKLY)); + List weekdayNums = rrule.getByDay(); + + if (weekdayNums.size() == 0) { + result += DateUtilities.ONE_WEEK * rrule.getInterval(); + return result; + } + HashSet weekdays = new HashSet(); + for (WeekdayNum curr : weekdayNums) { + weekdays.add(curr.wday); + } + + Weekday[] allWeekdays = Weekday.values(); + result -= DateUtilities.ONE_DAY; + Date date = new Date(result); + Weekday start = allWeekdays[date.getDay()]; + int i; + for (i = 0; i < allWeekdays.length; i++) { + if (start == allWeekdays[i]) break; + } + int index = i; + int daysToAdd = 0; + Weekday next = null; + for (i = index + 1; i < allWeekdays.length; i++) { + Weekday curr = allWeekdays[i]; + daysToAdd++; + if (weekdays.contains(curr)) { + next = curr; + break; + } + } + + if (next == null) { + for (i = 0; i < index + 1; i++) { + Weekday curr = allWeekdays[i]; + daysToAdd++; + if (weekdays.contains(curr)) { + next = curr; + break; + } + } + } + + if (fromCompletion) { + result += DateUtilities.ONE_WEEK * (rrule.getInterval() - 1); + } + result += DateUtilities.ONE_DAY * daysToAdd; + return result; + } + + + /** Advanced weekly repeating tests */ + protected long computeNextDueDateFromDate(long fromDate, RRule rrule, boolean fromCompletion) { + long expectedTime = fromDate; + Frequency frequency = rrule.getFreq(); + int interval = rrule.getInterval(); + if (frequency.equals(Frequency.MINUTELY)) { + expectedTime += DateUtilities.ONE_MINUTE * interval; + } else if (frequency.equals(Frequency.HOURLY)) { + expectedTime += DateUtilities.ONE_HOUR * interval; + } else if (frequency.equals(Frequency.DAILY)) { + expectedTime += DateUtilities.ONE_DAY * interval; + } else if (frequency.equals(Frequency.WEEKLY)) { + expectedTime = computeWeeklyCaseDueDate(fromDate, rrule, fromCompletion); + } else if (frequency.equals(Frequency.MONTHLY)) { + Date originalDate = new Date(expectedTime); + for (int i = 0; i < interval; i++) { + int month = originalDate.getMonth(); + if (month == 11) { // Roll over the year and set the month to January + originalDate.setYear(originalDate.getYear() + 1); + originalDate.setMonth(0); + } else { + originalDate.setMonth(originalDate.getMonth() + 1); + } + } + expectedTime = originalDate.getTime(); + } else if (frequency.equals(Frequency.YEARLY)) { + Date originalCompleteDate = new Date(expectedTime); + originalCompleteDate.setYear(originalCompleteDate.getYear() + interval); + expectedTime = originalCompleteDate.getTime(); + } + return expectedTime; + } + + private void testFromDueDate(boolean completeBefore, Frequency frequency, String title) { + testRepeating(completeBefore, false, null, frequency, title); + } + + private void testFromCompletionDate(boolean completeBefore, Frequency frequency, String title) { + testRepeating(completeBefore, true, null, frequency, title); + } + + + /** Tests for repeating from due date */ + + public void testRepeatMinutelyFromDueDateCompleteBefore() { + testFromDueDate(true, Frequency.MINUTELY, "minutely-before"); + } + + public void testRepeatMinutelyFromDueDateCompleteAfter() { + testFromDueDate(false, Frequency.MINUTELY, "minutely-after"); + } + + public void testRepeatHourlyFromDueDateCompleteBefore() { + testFromDueDate(true, Frequency.HOURLY, "hourly-before"); + } + + public void testRepeatHourlyFromDueDateCompleteAfter() { + testFromDueDate(false, Frequency.HOURLY, "hourly-after"); + } + + public void testRepeatDailyFromDueDateCompleteBefore() { + testFromDueDate(true, Frequency.DAILY, "daily-before"); + } + + public void testRepeatDailyFromDueDateCompleteAfter() { + testFromDueDate(false, Frequency.DAILY, "daily-after"); + } + + public void testRepeatWeeklyFromDueDateCompleteBefore() { + testFromDueDate(true, Frequency.WEEKLY, "weekly-before"); + } + + public void testRepeatWeeklyFromDueDateCompleteAfter() { + testFromDueDate(false, Frequency.WEEKLY, "weekly-after"); + } + + public void testRepeatMonthlyFromDueDateCompleteBefore() { + testFromDueDate(true, Frequency.MONTHLY, "monthly-before"); + } + + public void testRepeatMonthlyFromDueDateCompleteAfter() { + testFromDueDate(false, Frequency.MONTHLY, "monthly-after"); + } + + public void testRepeatYearlyFromDueDateCompleteBefore() { + testFromDueDate(true, Frequency.YEARLY, "yearly-before"); + } + + public void testRepeatYearlyFromDueDateCompleteAfter() { + testFromDueDate(false, Frequency.YEARLY, "yearly-after"); + } + + + /** Tests for repeating from completionDate */ + + public void testRepeatMinutelyFromCompleteDateCompleteBefore() { + testFromCompletionDate(true, Frequency.MINUTELY, "minutely-before"); + } + + public void testRepeatMinutelyFromCompleteDateCompleteAfter() { + testFromCompletionDate(false, Frequency.MINUTELY, "minutely-after"); + } + + public void testRepeatHourlyFromCompleteDateCompleteBefore() { + testFromCompletionDate(true, Frequency.HOURLY, "hourly-before"); + } + + public void testRepeatHourlyFromCompleteDateCompleteAfter() { + testFromCompletionDate(false, Frequency.HOURLY, "hourly-after"); + } + + public void testRepeatDailyFromCompleteDateCompleteBefore() { + testFromCompletionDate(true, Frequency.DAILY, "daily-before"); + } + + public void testRepeatDailyFromCompleteDateCompleteAfter() { + testFromCompletionDate(false, Frequency.DAILY, "daily-after"); + } + + public void testRepeatWeeklyFromCompleteDateCompleteBefore() { + testFromCompletionDate(true, Frequency.WEEKLY, "weekly-before"); + } + + public void testRepeatWeeklyFromCompleteDateCompleteAfter() { + testFromCompletionDate(false, Frequency.WEEKLY, "weekly-after"); + } + + public void testRepeatMonthlyFromCompleteDateCompleteBefore() { + testFromCompletionDate(true, Frequency.MONTHLY, "monthly-before"); + } + + public void testRepeatMonthlyFromCompleteDateCompleteAfter() { + testFromCompletionDate(false, Frequency.MONTHLY, "monthly-after"); + } + + public void testRepeatYearlyFromCompleteDateCompleteBefore() { + testFromCompletionDate(true, Frequency.YEARLY, "yearly-before"); + } + + public void testRepeatYearlyFromCompleteDateCompleteAfter() { + testFromCompletionDate(false, Frequency.YEARLY, "yearly-after"); + } + + private void testAdvancedWeeklyFromCompleteDate(boolean completeBefore, String title) { + RRule rrule = new RRule(); + rrule.setFreq(Frequency.WEEKLY); + + int interval = 1; + rrule.setInterval(interval); + List weekdays = new ArrayList(); + weekdays.add(new WeekdayNum(0, Weekday.MO)); + weekdays.add(new WeekdayNum(0, Weekday.WE)); + rrule.setByDay(weekdays); + testRepeating(completeBefore, true, rrule, Frequency.WEEKLY, title); + } + + + + // disabled until test can be fixed + public void testAdvancedRepeatWeeklyFromDueDateCompleteBefore() { + // testAdvancedWeeklyFromDueDate(true, "advanced-weekly-before"); + } + + public void testAdvancedRepeatWeeklyFromDueDateCompleteAfter() { + // testAdvancedWeeklyFromDueDate(false, "advanced-weekly-after"); + } + + public void testAdvancedRepeatWeeklyFromCompleteDateCompleteBefore() { + testAdvancedWeeklyFromCompleteDate(true, "advanced-weekly-before"); + } + + public void testAdvancedRepeatWeeklyFromCompleteDateCompleteAfter() { + testAdvancedWeeklyFromCompleteDate(false, "advanced-weekly-after"); + } +} diff --git a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSync.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSync.java similarity index 98% rename from tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSync.java rename to tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSync.java index 1326e3564..5afa12649 100644 --- a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSync.java +++ b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSync.java @@ -23,12 +23,11 @@ import com.todoroo.astrid.actfm.sync.ActFmSyncService; import com.todoroo.astrid.dao.TaskDao.TaskCriteria; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.Task; -import com.todoroo.astrid.repeats.NewRepeatTests; import com.todoroo.astrid.repeats.RepeatTaskCompleteListener; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.StartupService; -public class RepeatTestsActFmSync extends NewRepeatTests { +public class RepeatTestsActFmSync extends AbstractSyncRepeatTests { @Autowired MetadataService metadataService; @Autowired ActFmDataService actFmDataService; diff --git a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSyncRemote.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSyncRemote.java similarity index 100% rename from tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSyncRemote.java rename to tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsActFmSyncRemote.java diff --git a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSync.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSync.java similarity index 97% rename from tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSync.java rename to tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSync.java index d74b4ffa6..0ce53d716 100644 --- a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSync.java +++ b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSync.java @@ -26,11 +26,10 @@ import com.todoroo.astrid.gtasks.api.GtasksApiUtilities; import com.todoroo.astrid.gtasks.api.GtasksInvoker; import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator; import com.todoroo.astrid.gtasks.sync.GtasksSyncProvider; -import com.todoroo.astrid.repeats.NewRepeatTests; import com.todoroo.astrid.repeats.RepeatTaskCompleteListener; import com.todoroo.astrid.service.MetadataService; -public class RepeatTestsGtasksSync extends NewRepeatTests { +public class RepeatTestsGtasksSync extends AbstractSyncRepeatTests { @Autowired MetadataService metadataService; @Autowired GtasksMetadataService gtasksMetadataService; diff --git a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSyncRemote.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSyncRemote.java similarity index 95% rename from tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSyncRemote.java rename to tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSyncRemote.java index 2474d4ea7..0c45e0cb2 100644 --- a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSyncRemote.java +++ b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsGtasksSyncRemote.java @@ -1,7 +1,5 @@ package com.todoroo.astrid.sync.repeats; -import static com.todoroo.astrid.sync.repeats.RepeatTestsGtasksSync.DEFAULT_LIST; - import java.io.IOException; import java.util.Date; diff --git a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSync.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSync.java similarity index 97% rename from tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSync.java rename to tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSync.java index 7be074a63..5bc22dc97 100644 --- a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSync.java +++ b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSync.java @@ -14,12 +14,11 @@ import com.todoroo.astrid.producteev.api.ProducteevInvoker; import com.todoroo.astrid.producteev.sync.ProducteevDataService; import com.todoroo.astrid.producteev.sync.ProducteevSyncProvider; import com.todoroo.astrid.producteev.sync.ProducteevTask; -import com.todoroo.astrid.repeats.NewRepeatTests; import com.todoroo.astrid.service.MetadataService; import com.todoroo.astrid.service.TaskService; import com.todoroo.astrid.tags.TagService; -public class RepeatTestsProducteevSync extends NewRepeatTests { +public class RepeatTestsProducteevSync extends AbstractSyncRepeatTests { private static boolean initialized = false; diff --git a/tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSyncRemote.java b/tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSyncRemote.java similarity index 100% rename from tests/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSyncRemote.java rename to tests-sync/src/com/todoroo/astrid/sync/repeats/RepeatTestsProducteevSyncRemote.java diff --git a/tests-sync/src/com/todoroo/astrid/test/DatabaseTestCase.java b/tests-sync/src/com/todoroo/astrid/test/DatabaseTestCase.java new file mode 100644 index 000000000..d5ba2b008 --- /dev/null +++ b/tests-sync/src/com/todoroo/astrid/test/DatabaseTestCase.java @@ -0,0 +1,63 @@ +package com.todoroo.astrid.test; + +import java.io.File; + +import com.todoroo.astrid.dao.Database; +import com.todoroo.astrid.provider.Astrid3ContentProvider; +import com.todoroo.astrid.service.AstridDependencyInjector; + +/** + * Test case that automatically sets up and tears down a test database + * + * @author Tim Su + * + */ +public class DatabaseTestCase extends TodorooTestCaseWithInjector { + + static { + AstridDependencyInjector.initialize(); + } + + public static Database database = new TestDatabase(); + + @Override + protected void addInjectables() { + testInjector.addInjectable("database", database); + } + + @Override + protected void setUp() throws Exception { + // call upstream setup, which invokes dependency injector + super.setUp(); + + // empty out test databases + database.clear(); + database.openForWriting(); + + Astrid3ContentProvider.setDatabaseOverride(database); + } + + /** + * Helper to delete a database by name + * @param database + */ + protected void deleteDatabase(String database) { + File db = getContext().getDatabasePath(database); + if(db.exists()) + db.delete(); + } + + @Override + protected void tearDown() throws Exception { + database.close(); + super.tearDown(); + } + + public static class TestDatabase extends Database { + @Override + public String getName() { + return "databasetest"; + } + } + +} diff --git a/tests-sync/src/com/todoroo/astrid/test/TestDependencyInjector.java b/tests-sync/src/com/todoroo/astrid/test/TestDependencyInjector.java new file mode 100644 index 000000000..c92066bda --- /dev/null +++ b/tests-sync/src/com/todoroo/astrid/test/TestDependencyInjector.java @@ -0,0 +1,48 @@ +package com.todoroo.astrid.test; + +import com.todoroo.andlib.service.AbstractDependencyInjector; +import com.todoroo.andlib.service.DependencyInjectionService; + + +public class TestDependencyInjector extends AbstractDependencyInjector { + + private String name; + + public TestDependencyInjector(String name) { + this.name = name; + } + + public void addInjectable(String field, Object injection) { + injectables.put(field, injection); + } + + @Override + protected void addInjectables() { + // do nothing, we populate injectables via the addInjectable method + } + + @Override + public String toString() { + return "TestDI:" + name; + } + + // --- static stuff + + /** + * Install TestDependencyInjector above other injectors + */ + public synchronized static TestDependencyInjector initialize(String name) { + TestDependencyInjector instance = new TestDependencyInjector(name); + DependencyInjectionService.getInstance().addInjector(instance); + return instance; + } + + /** + * Remove an installed TestDependencyInjector + * @param string + */ + public static void deinitialize(TestDependencyInjector instance) { + DependencyInjectionService.getInstance().removeInjector(instance); + } + +} diff --git a/tests-sync/src/com/todoroo/astrid/test/TestUtilities.java b/tests-sync/src/com/todoroo/astrid/test/TestUtilities.java new file mode 100644 index 000000000..8deced342 --- /dev/null +++ b/tests-sync/src/com/todoroo/astrid/test/TestUtilities.java @@ -0,0 +1,25 @@ +package com.todoroo.astrid.test; + + +/** + * Utility methods used in unit tests + * + * @author Tim Su + * + */ +public class TestUtilities { + + /** + * Sleep, suppressing exceptions + * + * @param millis + */ + public static void sleepDeep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + // do nothing + } + } + +} diff --git a/tests-sync/src/com/todoroo/astrid/test/TodorooTestCase.java b/tests-sync/src/com/todoroo/astrid/test/TodorooTestCase.java new file mode 100644 index 000000000..c94f9ed3c --- /dev/null +++ b/tests-sync/src/com/todoroo/astrid/test/TodorooTestCase.java @@ -0,0 +1,66 @@ +package com.todoroo.astrid.test; + +import java.util.Locale; + +import android.content.res.Configuration; +import android.test.AndroidTestCase; +import android.util.DisplayMetrics; + +import com.todoroo.andlib.service.ContextManager; +import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.astrid.service.AstridDependencyInjector; + +/** + * Base test case for Astrid tests + * + * @author Tim Su + * + */ +public class TodorooTestCase extends AndroidTestCase { + + static { + AstridDependencyInjector.initialize(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + ContextManager.setContext(this.getContext()); + AstridDependencyInjector.flush(); + DependencyInjectionService.getInstance().inject(this); + setLocale(Locale.ENGLISH); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + setLocale(Locale.getDefault()); + } + + /** + * Loop through each locale and call runnable + * @param r + */ + public void forEachLocale(Runnable r) { + Locale[] locales = Locale.getAvailableLocales(); + for(Locale locale : locales) { + setLocale(locale); + + r.run(); + } + } + + /** + * Sets locale + * @param locale + */ + private void setLocale(Locale locale) { + Locale.setDefault(locale); + Configuration config = new Configuration(); + config.locale = locale; + DisplayMetrics metrics = getContext().getResources().getDisplayMetrics(); + getContext().getResources().updateConfiguration(config, metrics); + } + +} diff --git a/tests-sync/src/com/todoroo/astrid/test/TodorooTestCaseWithInjector.java b/tests-sync/src/com/todoroo/astrid/test/TodorooTestCaseWithInjector.java new file mode 100644 index 000000000..332d08f11 --- /dev/null +++ b/tests-sync/src/com/todoroo/astrid/test/TodorooTestCaseWithInjector.java @@ -0,0 +1,31 @@ +package com.todoroo.astrid.test; + + +/** + * Base test case for Astrid tests that need a separate injection context + * + * @author Tim Su + * + */ +abstract public class TodorooTestCaseWithInjector extends TodorooTestCase { + + protected TestDependencyInjector testInjector; + + abstract protected void addInjectables(); + + @Override + protected void setUp() throws Exception { + testInjector = TestDependencyInjector.initialize("test"); + addInjectables(); + + super.setUp(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + + TestDependencyInjector.deinitialize(testInjector); + } + +} diff --git a/tests-sync/src/com/zutubi/android/junitreport/JUnitReportListener.java b/tests-sync/src/com/zutubi/android/junitreport/JUnitReportListener.java new file mode 100644 index 000000000..4022856fd --- /dev/null +++ b/tests-sync/src/com/zutubi/android/junitreport/JUnitReportListener.java @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2010 Zutubi Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zutubi.android.junitreport; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestListener; + +import org.xmlpull.v1.XmlSerializer; + +import android.content.Context; +import android.util.Log; +import android.util.Xml; + +/** + * Custom test listener that outputs test results to a single XML file. The file + * uses a similar format the to Ant JUnit task XML formatter, with a couple of + * caveats: + *
    + *
  • Multiple suites are all placed in a single file under a root + * <testsuites> element.
  • + *
  • Redundant information about the number of nested cases within a suite is + * omitted.
  • + *
  • Neither standard output nor system properties are included.
  • + *
+ * The differences mainly revolve around making this reporting as lightweight as + * possible. The report is streamed as the tests run, making it impossible to, + * e.g. include the case count in a <testsuite> element. + */ +public class JUnitReportListener implements TestListener { + private static final String LOG_TAG = "JUnitReportListener"; + + private static final String ENCODING_UTF_8 = "utf-8"; + + private static final String TAG_SUITES = "testsuites"; + private static final String TAG_SUITE = "testsuite"; + private static final String TAG_CASE = "testcase"; + private static final String TAG_ERROR = "error"; + private static final String TAG_FAILURE = "failure"; + + private static final String ATTRIBUTE_NAME = "name"; + private static final String ATTRIBUTE_CLASS = "classname"; + private static final String ATTRIBUTE_TYPE = "type"; + private static final String ATTRIBUTE_MESSAGE = "message"; + private static final String ATTRIBUTE_TIME = "time"; + + // With thanks to org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner. + // Trimmed some entries, added others for Android. + private static final String[] DEFAULT_TRACE_FILTERS = new String[] { + "junit.framework.TestCase", "junit.framework.TestResult", + "junit.framework.TestSuite", + "junit.framework.Assert.", // don't filter AssertionFailure + "java.lang.reflect.Method.invoke(", "sun.reflect.", + // JUnit 4 support: + "org.junit.", "junit.framework.JUnit4TestAdapter", " more", + // Added for Android + "android.test.", "android.app.Instrumentation", + "java.lang.reflect.Method.invokeNative", + }; + + private Context mContext; + private String mReportFilePath; + private boolean mFilterTraces; + private FileOutputStream mOutputStream; + private XmlSerializer mSerializer; + private String mCurrentSuite; + + // simple time tracking + private boolean timeAlreadyWritten = false; + private long testStart; + + /** + * Creates a new listener. + * + * @param context context of the target application under test + * @param reportFilePath path of the report file to create (under the + * context using {@link Context#openFileOutput(String, int)}). + * @param filterTraces if true, stack traces will have common noise (e.g. + * framework methods) omitted for clarity + */ + public JUnitReportListener(Context context, String reportFilePath, boolean filterTraces) { + this.mContext = context; + this.mReportFilePath = reportFilePath; + this.mFilterTraces = filterTraces; + } + + public void startTest(Test test) { + try { + openIfRequired(test); + + if (test instanceof TestCase) { + TestCase testCase = (TestCase) test; + checkForNewSuite(testCase); + testStart = System.currentTimeMillis(); + timeAlreadyWritten = false; + mSerializer.startTag("", TAG_CASE); + mSerializer.attribute("", ATTRIBUTE_CLASS, mCurrentSuite); + mSerializer.attribute("", ATTRIBUTE_NAME, testCase.getName()); + } + } catch (IOException e) { + Log.e(LOG_TAG, safeMessage(e)); + } + } + + private void checkForNewSuite(TestCase testCase) throws IOException { + String suiteName = testCase.getClass().getName(); + if (mCurrentSuite == null || !mCurrentSuite.equals(suiteName)) { + if (mCurrentSuite != null) { + mSerializer.endTag("", TAG_SUITE); + } + + mSerializer.startTag("", TAG_SUITE); + mSerializer.attribute("", ATTRIBUTE_NAME, suiteName); + mCurrentSuite = suiteName; + } + } + + private void openIfRequired(Test test) throws IOException { + if (mOutputStream == null) { + mOutputStream = mContext.openFileOutput(mReportFilePath, 0); + mSerializer = Xml.newSerializer(); + mSerializer.setOutput(mOutputStream, ENCODING_UTF_8); + mSerializer.startDocument(ENCODING_UTF_8, true); + mSerializer.startTag("", TAG_SUITES); + } + } + + public void addError(Test test, Throwable error) { + addProblem(TAG_ERROR, error); + } + + public void addFailure(Test test, AssertionFailedError error) { + addProblem(TAG_FAILURE, error); + } + + private void addProblem(String tag, Throwable error) { + try { + recordTestTime(); + + mSerializer.startTag("", tag); + mSerializer.attribute("", ATTRIBUTE_MESSAGE, safeMessage(error)); + mSerializer.attribute("", ATTRIBUTE_TYPE, error.getClass().getName()); + StringWriter w = new StringWriter(); + error.printStackTrace(mFilterTraces ? new FilteringWriter(w) : new PrintWriter(w)); + mSerializer.text(w.toString()); + mSerializer.endTag("", tag); + } catch (IOException e) { + Log.e(LOG_TAG, safeMessage(e)); + } + } + + private void recordTestTime() throws IOException { + if(!timeAlreadyWritten) { + timeAlreadyWritten = true; + mSerializer.attribute("", ATTRIBUTE_TIME, + String.format("%.3f", (System.currentTimeMillis() - testStart) / 1000.)); + } + } + + public void endTest(Test test) { + try { + if (test instanceof TestCase) { + recordTestTime(); + mSerializer.endTag("", TAG_CASE); + } + } catch (IOException e) { + Log.e(LOG_TAG, safeMessage(e)); + } + } + + /** + * Releases all resources associated with this listener. Must be called + * when the listener is finished with. + */ + public void close() { + if (mSerializer != null) { + try { + if (mCurrentSuite != null) { + mSerializer.endTag("", TAG_SUITE); + } + + mSerializer.endTag("", TAG_SUITES); + mSerializer.endDocument(); + mSerializer = null; + } catch (IOException e) { + Log.e(LOG_TAG, safeMessage(e)); + } + } + + if (mOutputStream != null) { + try { + mOutputStream.close(); + mOutputStream = null; + } catch (IOException e) { + Log.e(LOG_TAG, safeMessage(e)); + } + } + } + + private String safeMessage(Throwable error) { + String message = error.getMessage(); + return error.getClass().getName() + ": " + (message == null ? "" : message); + } + + /** + * Wrapper around a print writer that filters out common noise from stack + * traces, making it easier to see the actual failure. + */ + private static class FilteringWriter extends PrintWriter { + public FilteringWriter(Writer out) { + super(out); + } + + @Override + public void println(String s) { + for (String filtered : DEFAULT_TRACE_FILTERS) { + if (s.contains(filtered)) { + return; + } + } + + super.println(s); + } + } +} diff --git a/tests-sync/src/com/zutubi/android/junitreport/JUnitReportTestRunner.java b/tests-sync/src/com/zutubi/android/junitreport/JUnitReportTestRunner.java new file mode 100644 index 000000000..863e17f65 --- /dev/null +++ b/tests-sync/src/com/zutubi/android/junitreport/JUnitReportTestRunner.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 Zutubi Pty Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.zutubi.android.junitreport; + +import android.os.Bundle; +import android.test.AndroidTestRunner; +import android.test.InstrumentationTestRunner; + +/** + * Custom test runner that adds a {@link JUnitReportListener} to the underlying + * test runner in order to capture test results in an XML report. You may use + * this class in place of {@link InstrumentationTestRunner} in your test + * project's manifest, and/or specify it to your Ant build using the test.runner + * property. + *

+ * This runner behaves identically to the default, with the added side-effect of + * producing a JUnit XML report. The report format is similar to that produced + * by the Ant JUnit task's XML formatter, making it compatible with existing + * tools that can process that format. See {@link JUnitReportListener} for + * further details. + *

+ * This runner accepts the following arguments: + *

    + *
  • reportFilePath: path of the file to write the XML report to, in the + * target application's data area (default: junit-report.xml).
  • + *
  • filterTraces: if true, stack traces in test failure reports will be + * filtered to remove noise such as framework methods (default: true)
  • + *
+ * These arguments may be specified as follows: + * + *
+ * {@code adb shell am instrument -w -e reportFile my-report-file.xml}
+ * 
+ */ +public class JUnitReportTestRunner extends InstrumentationTestRunner { + /** + * Path, relative to the target applications file root, at which to write the report file. + */ + private static final String ARG_REPORT_FILE_PATH = "reportFilePath"; + /** + * If true, stack traces in the report will be filtered to remove common noise (e.g. framework + * methods). + */ + private static final String ARG_FILTER_TRACES = "filterTraces"; + /** + * Default path of the report file. + */ + private static final String DEFAULT_REPORT_FILE = "junit-report.xml"; + + private JUnitReportListener mListener; + private String mReportFilePath; + private boolean mFilterTraces = true; + + @Override + public void onCreate(Bundle arguments) { + if (arguments != null) { + mReportFilePath = arguments.getString(ARG_REPORT_FILE_PATH); + mFilterTraces = arguments.getBoolean(ARG_FILTER_TRACES, true); + } + + if (mReportFilePath == null) { + mReportFilePath = DEFAULT_REPORT_FILE; + } + + super.onCreate(arguments); + } + + @Override + protected AndroidTestRunner getAndroidTestRunner() { + AndroidTestRunner runner = new AndroidTestRunner(); + mListener = new JUnitReportListener(getTargetContext(), mReportFilePath, mFilterTraces); + runner.addTestListener(mListener); + return runner; + } + + @Override + public void finish(int resultCode, Bundle results) { + if (mListener != null) { + mListener.close(); + } + + super.finish(resultCode, results); + } +} diff --git a/tests/src/com/todoroo/astrid/ActivityTests.java b/tests/src/com/todoroo/astrid/ActivityTests.java deleted file mode 100644 index 24ee77fb5..000000000 --- a/tests/src/com/todoroo/astrid/ActivityTests.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.todoroo.astrid; - -import junit.framework.Test; -import junit.framework.TestSuite; - -import android.test.suitebuilder.TestSuiteBuilder; - -/** - * A test suite containing activity-related tests - */ -public class ActivityTests extends TestSuite { - - public static Test suite() { - return new TestSuiteBuilder(ActivityTests.class) - .includePackages("com.todoroo.astrid.activity") - .build(); - } -} diff --git a/tests/src/com/todoroo/astrid/AllTests.java b/tests/src/com/todoroo/astrid/AllTests.java index ee8584ee1..0c715e0da 100644 --- a/tests/src/com/todoroo/astrid/AllTests.java +++ b/tests/src/com/todoroo/astrid/AllTests.java @@ -46,10 +46,6 @@ public class AllTests extends TestSuite { public static Test suite() { return new TestSuiteBuilder(AllTests.class) - .excludePackages( - "com.todoroo.astrid.gtasks", - "com.todoroo.astrid.producteev", - "com.todoroo.astrid.sync.repeats") .build(); } } diff --git a/tests/src/com/todoroo/astrid/ContinuousTests.java b/tests/src/com/todoroo/astrid/ContinuousTests.java deleted file mode 100644 index 543024650..000000000 --- a/tests/src/com/todoroo/astrid/ContinuousTests.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.todoroo.astrid; - -import junit.framework.Test; -import junit.framework.TestSuite; -import android.test.suitebuilder.TestSuiteBuilder; - -/** - * A test suite containing all tests for ApiDemos. - * - * To run all suites found in this apk: - * $ adb shell am instrument -w \ - * com.example.android.apis.tests/android.test.InstrumentationTestRunner - * - * To run just this suite from the command line: - * $ adb shell am instrument -w \ - * -e class com.example.android.apis.AllTests \ - * com.example.android.apis.tests/android.test.InstrumentationTestRunner - * - * To run an individual test case, e.g. {@link com.example.android.apis.os.MorseCodeConverterTest}: - * $ adb shell am instrument -w \ - * -e class com.example.android.apis.os.MorseCodeConverterTest \ - * com.example.android.apis.tests/android.test.InstrumentationTestRunner - * - * To run an individual test, e.g. {@link com.example.android.apis.os.MorseCodeConverterTest#testCharacterS()}: - * $ adb shell am instrument -w \ - * -e class com.example.android.apis.os.MorseCodeConverterTest#testCharacterS \ - * com.example.android.apis.tests/android.test.InstrumentationTestRunner - */ -public class ContinuousTests extends TestSuite { - - public static Test suite() { - return new TestSuiteBuilder(ContinuousTests.class) - .excludePackages( - "com.todoroo.astrid.gtasks", - "com.todoroo.astrid.producteev", - "com.todoroo.astrid.sync.repeats") - .build(); - } -} diff --git a/tests/src/com/todoroo/astrid/NightlyTests.java b/tests/src/com/todoroo/astrid/NightlyTests.java deleted file mode 100644 index ee32fb7b9..000000000 --- a/tests/src/com/todoroo/astrid/NightlyTests.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.todoroo.astrid; - -import junit.framework.Test; -import junit.framework.TestSuite; -import android.test.suitebuilder.TestSuiteBuilder; - -/** - * A test suite containing activity-related tests - */ -public class NightlyTests extends TestSuite { - - public static Test suite() { - return new TestSuiteBuilder(NightlyTests.class) - .includeAllPackagesUnderHere() - .build(); - } - - -}