Java tutorial
/* * Vulcan Build Manager * Copyright (C) 2005-2012 Chris Eldredge * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package net.sourceforge.vulcan.spring.jdbc; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; import junit.framework.TestCase; import net.sourceforge.vulcan.core.support.StoreStub; import net.sourceforge.vulcan.dto.BuildMessageDto; import net.sourceforge.vulcan.dto.BuildOutcomeQueryDto; import net.sourceforge.vulcan.dto.ChangeLogDto; import net.sourceforge.vulcan.dto.ChangeSetDto; import net.sourceforge.vulcan.dto.MetricDto; import net.sourceforge.vulcan.dto.ModifiedPathDto; import net.sourceforge.vulcan.dto.PathModification; import net.sourceforge.vulcan.dto.ProjectStatusDto; import net.sourceforge.vulcan.dto.RevisionTokenDto; import net.sourceforge.vulcan.dto.TestFailureDto; import net.sourceforge.vulcan.dto.MetricDto.MetricType; import net.sourceforge.vulcan.dto.ProjectStatusDto.Status; import net.sourceforge.vulcan.dto.ProjectStatusDto.UpdateType; import net.sourceforge.vulcan.exception.StoreException; import org.apache.commons.lang.StringUtils; import org.springframework.core.io.Resource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SingleConnectionDataSource; public class JdbcBuildOutcomeStoreTest extends TestCase { JdbcBuildOutcomeStore store = new JdbcBuildOutcomeStore(); SingleConnectionDataSource dataSource = new SingleConnectionDataSource(); JdbcBuildOutcomeDto outcome = new JdbcBuildOutcomeDto(); boolean initCalled = false; boolean diffExistsFlag = false; boolean buildLogExistsFlag = false; @Override protected void setUp() throws Exception { super.setUp(); final Properties props = new Properties(); props.setProperty("autocommit", "false"); dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); dataSource.setUrl("jdbc:hsqldb:mem:JdbcBuildOutcomeStoreTest"); dataSource.setUsername("sa"); dataSource.setPassword(""); dataSource.setConnectionProperties(props); dataSource.setAutoCommit(false); store.setConfigurationStore(new StoreStub(null) { @Override public boolean diffExists(String projectName, UUID diffId) { return diffExistsFlag; } @Override public boolean buildLogExists(String projectName, UUID diffId) { return buildLogExistsFlag; } }); store.setDataSource(dataSource); final Map<String, String> queries = new HashMap<String, String>(); queries.put("select.average.build.time", "select avg(elapsed) / 1000000 from (select top 10 datediff('ms', start_date, completion_date) as elapsed " + "from builds inner join project_names on builds.project_id = project_names.id " + "where name=? and update_type=? and status='PASS' order by build_number desc)"); store.setSqlQueries(queries); outcome.setId(UUID.randomUUID()); outcome.setStatus(Status.PASS); outcome.setName("project-a"); outcome.setBuildNumber(5); outcome.setBuildReasonKey("x.y.z"); outcome.setMessageKey("r.x.t"); outcome.setStartDate(new Date(10004000L)); outcome.setCompletionDate(new Date(20004000L)); final JdbcSchemaMigrator migrator = new JdbcSchemaMigrator(); migrator.setCreateTablesScript(JdbcSchemaMigratorTest.resolveSqlScript("create_tables.sql")); Resource[] scripts = JdbcSchemaMigratorTest.getMigrationScripts(); migrator.setMigrationScripts(scripts); migrator.setDataSource(dataSource); migrator.updateSchema(); } @Override protected void tearDown() throws Exception { new JdbcTemplate(dataSource).execute("shutdown;"); super.tearDown(); } public void testInitCreatesTablesWhenMissing() throws Exception { store.init(); int count = new JdbcTemplate(dataSource).queryForInt("select count(1) from builds"); assertEquals(0, count); } public void testInitDoesNotThrowWhenTableAlreadyPresent() throws Exception { store.init(); store.init(); int count = new JdbcTemplate(dataSource).queryForInt("select count(1) from builds"); assertEquals(0, count); } public void testSaveSimple() throws Exception { assertPersistence(); } public void testSaveWithBrokenByUsesr() throws Exception { outcome.setBrokenBy("lazy user"); outcome.setClaimDate(new Date(12314423l)); assertPersistence(); } public void testSaveWithWorkDirFlag() throws Exception { outcome.setWorkDirSupportsIncrementalUpdate(true); assertPersistence(); } public void testClaimBrokenBuild() throws Exception { final JdbcBuildOutcomeDto before = storeOutcome(); final Date date = new Date(12345l); store.claimBrokenBuild(before.getId(), "lazy user", date); final JdbcBuildOutcomeDto after = store.loadBuildOutcome(before.getId()); assertEquals("lazy user", after.getBrokenBy()); assertEquals(date, after.getClaimDate()); } public void testClaimBrokenBuildCaseInsensitiveUsername() throws Exception { final JdbcBuildOutcomeDto first = storeOutcome(); final Date date = new Date(12345l); store.claimBrokenBuild(first.getId(), "Lazy User", date); final JdbcBuildOutcomeDto firstResult = store.loadBuildOutcome(first.getId()); assertEquals("Lazy User", firstResult.getBrokenBy()); assertEquals(date, firstResult.getClaimDate()); outcome.setBuildNumber(outcome.getBuildNumber() + 1); outcome.setId(null); outcome.setBrokenBy(null); outcome.setClaimDate(null); final JdbcBuildOutcomeDto second = storeOutcome(); store.claimBrokenBuild(second.getId(), "LAZY USER", date); final JdbcBuildOutcomeDto secondResult = store.loadBuildOutcome(second.getId()); assertEquals("Lazy User", secondResult.getBrokenBy()); } public void testClaimBrokenBuildLeavesOthers() throws Exception { final JdbcBuildOutcomeDto other = storeOutcome(); final Date date = new Date(12345l); outcome.setBuildNumber(outcome.getBuildNumber() + 1); outcome.setId(null); final JdbcBuildOutcomeDto before = storeOutcome(); store.claimBrokenBuild(before.getId(), "lazy user", date); final JdbcBuildOutcomeDto after = store.loadBuildOutcome(before.getId()); assertEquals("lazy user", after.getBrokenBy()); assertNotNull(after.getClaimDate()); final JdbcBuildOutcomeDto otherAfter = store.loadBuildOutcome(other.getId()); assertNull(otherAfter.getBrokenBy()); assertNull(otherAfter.getClaimDate()); } public void testSaveEmptyBrokenByUsesrDoesNotSetClaimedDate() throws Exception { outcome.setBrokenBy(null); outcome.setClaimDate(new Date(12314423l)); final JdbcBuildOutcomeDto result = storeOutcome(); outcome.setClaimDate(null); assertPersistence(result); } public void testThrowsStoreException() throws Exception { store.init(); outcome.setBuildNumber(null); try { store.storeBuildOutcome(outcome); fail("Expected exception"); } catch (StoreException e) { assertTrue(e.getCause() instanceof DataAccessException); } } public void testSaveTwoReusesProjectName() throws Exception { assertPersistence(); outcome.setBuildNumber(6); outcome.setId(UUID.randomUUID()); assertPersistence(); } public void testLoadByWorkDir() throws Exception { outcome.setWorkDir("dir"); JdbcBuildOutcomeDto a = storeOutcome(); outcome.setBuildNumber(6); outcome.setId(UUID.randomUUID()); outcome.setWorkDir("other"); storeOutcome(); ProjectStatusDto actual = store.loadMostRecentBuildOutcomeByWorkDir(a.getName(), a.getWorkDir()); assertEquals(a, actual); } public void testLoadByWorkDirNotFound() throws Exception { outcome.setWorkDir("dir"); JdbcBuildOutcomeDto a = storeOutcome(); outcome.setBuildNumber(6); outcome.setId(UUID.randomUUID()); outcome.setWorkDir("other"); storeOutcome(); ProjectStatusDto actual = store.loadMostRecentBuildOutcomeByWorkDir(a.getName(), a.getWorkDir() + "2"); assertEquals(null, actual); } public void testLoadByTag() throws Exception { outcome.setTagName("trunk"); JdbcBuildOutcomeDto a = storeOutcome(); outcome.setBuildNumber(6); outcome.setId(UUID.randomUUID()); outcome.setTagName("tags/other"); storeOutcome(); outcome.setId(UUID.randomUUID()); outcome.setName("otherproject"); storeOutcome(); ProjectStatusDto actual = store.loadMostRecentBuildOutcomeByTagName(a.getName(), a.getTagName()); assertEquals(a, actual); } public void testRenameProject() throws Exception { assertPersistence(); store.projectNameChanged(outcome.getName(), "newName"); outcome.setName("newName"); outcome.setBuildNumber(6); outcome.setId(UUID.randomUUID()); assertPersistence(); } public void testRenameProjectBeforeSavingFirstBuild() throws Exception { store.init(); initCalled = true; store.projectNameChanged(outcome.getName(), "newName"); outcome.setName("newName"); assertPersistence(); } /** * See http://code.google.com/p/vulcan/issues/detail?id=155 */ public void testRenameProjectMergesExisting() throws Exception { assertPersistence(); final String existingName = outcome.getName(); final String otherName = existingName + "-2"; outcome.setName(otherName); outcome.setId(UUID.randomUUID()); assertPersistence(); store.projectNameChanged(otherName, existingName); final BuildOutcomeQueryDto query = new BuildOutcomeQueryDto(); query.setProjectNames(Collections.singleton(existingName)); final List<ProjectStatusDto> list = store.loadBuildSummaries(query); assertEquals(1, list.size()); } public void testSaveGeneratesIdOnNull() throws Exception { store.init(); outcome.setId(null); outcome.setStatus(Status.SKIP); outcome.setUpdateType(null); final UUID id = store.storeBuildOutcome(outcome); assertSame(id, outcome.getId()); assertPersistence(store.loadBuildOutcome(id)); } public void testSaveOptionalColumns() throws Exception { outcome.setUpdateType(UpdateType.Incremental); outcome.setWorkDir("a work dir"); outcome.setRevision(new RevisionTokenDto(342l, "r342")); outcome.setLastGoodBuildNumber(43432); outcome.setTagName("a/tag"); outcome.setRepositoryUrl("http://example.com"); outcome.setStatusChanged(true); outcome.setScheduledBuild(true); outcome.setRequestedBy("Jessica"); assertPersistence(); } public void testLoadBuildSchedulersAndUsers() throws Exception { outcome.setRequestedBy("Brook"); outcome.setScheduledBuild(false); storeOutcome(); outcome.setId(UUID.randomUUID()); outcome.setBuildNumber(42); outcome.setRequestedBy("Cyborg"); outcome.setScheduledBuild(true); storeOutcome(); List<String> scheds = store.getBuildSchedulers(); assertEquals(1, scheds.size()); assertEquals("Cyborg", scheds.get(0)); List<String> users = store.getBuildUsers(); assertEquals(1, users.size()); assertEquals("Brook", users.get(0)); } public void testLoadBuildUsersIgnoresNull() throws Exception { outcome.setRequestedBy(null); outcome.setScheduledBuild(false); storeOutcome(); List<String> scheds = store.getBuildUsers(); assertEquals(0, scheds.size()); } public void testStoresNewBuildUserAfterInitialized() throws Exception { outcome.setRequestedBy(null); outcome.setScheduledBuild(false); storeOutcome(); store.getBuildUsers(); outcome.setId(UUID.randomUUID()); outcome.setBuildNumber(42); outcome.setRequestedBy("Susan"); storeOutcome(); List<String> users = store.getBuildUsers(); assertEquals(1, users.size()); assertEquals("Susan", users.get(0)); } public void testStoresNewBuildUserAfterInitializedUnlessAlreadyDefined() throws Exception { outcome.setRequestedBy("Susan"); outcome.setScheduledBuild(false); storeOutcome(); store.getBuildUsers(); outcome.setId(UUID.randomUUID()); outcome.setBuildNumber(42); outcome.setRequestedBy("Susan"); storeOutcome(); List<String> users = store.getBuildUsers(); assertEquals(1, users.size()); assertEquals("Susan", users.get(0)); } public void testFindMostRecentBuildNumberByWorkingCopy() throws Exception { outcome.setWorkDir("a work dir"); assertPersistence(); outcome.setId(UUID.randomUUID()); outcome.setBuildNumber(42); assertPersistence(); assertEquals(outcome.getBuildNumber(), store.findMostRecentBuildNumberByWorkDir(outcome.getWorkDir())); } public void testFindMostRecentBuildNumberByWorkingCopyNull() throws Exception { store.init(); assertEquals(null, store.findMostRecentBuildNumberByWorkDir("never used")); } public void testSaveLastKnownRevision() throws Exception { outcome.setRevision(null); outcome.setLastKnownRevision(new RevisionTokenDto(342l, "r342")); assertPersistence(); } public void testSaveMessageArg() throws Exception { outcome.setMessageArgs(new Object[] { "a" }); assertPersistence(); } public void testTruncateMessageArg() throws Exception { outcome.setMessageArgs(new Object[] { StringUtils.repeat("abcd", 65) }); JdbcBuildOutcomeDto result = storeOutcome(); outcome.getMessageArgs()[0] = StringUtils.repeat("abcd", 63) + "a..."; assertPersistence(result); } public void testSaveFourMessageArgs() throws Exception { outcome.setMessageArgs(new Object[] { "a", "b", "c", "d" }); assertPersistence(); } public void testSaveFourBuildReasonArgs() throws Exception { outcome.setBuildReasonArgs(new Object[] { "a", "b", "c", "d" }); assertPersistence(); } public void testGetBuildOutcomeIds() throws Exception { store.init(); outcome.setName("a"); store.storeBuildOutcome(outcome); outcome.setName("b"); outcome.setId(UUID.randomUUID()); store.storeBuildOutcome(outcome); outcome.setName("a"); outcome.setBuildNumber(3242); outcome.setId(UUID.randomUUID()); store.storeBuildOutcome(outcome); final Map<String, List<UUID>> map = store.getBuildOutcomeIDs(); assertNotNull(map); assertEquals(2, map.size()); assertTrue(map.containsKey("a")); assertTrue(map.containsKey("b")); assertEquals(2, map.get("a").size()); assertEquals(1, map.get("b").size()); } public void testSaveDependencies() throws Exception { final String depName1 = outcome.getName(); final UUID depId1 = outcome.getId(); assertPersistence(); outcome.setName("service"); outcome.setId(UUID.randomUUID()); final String depName2 = outcome.getName(); final UUID depId2 = outcome.getId(); assertPersistence(); outcome.setName("ui"); outcome.setId(UUID.randomUUID()); final HashMap<String, UUID> depMap = new HashMap<String, UUID>(); outcome.setDependencyIds(depMap); depMap.put(depName1, depId1); depMap.put(depName2, depId2); assertPersistence(); } public void testSaveWarnings() throws Exception { outcome.setWarnings(Arrays.<BuildMessageDto>asList( new JdbcBuildMessageDto("sample message", "a file", 43, "X12", BuildMessageType.Warning), new JdbcBuildMessageDto("another sample message", "a file", 44, "X13", BuildMessageType.Warning))); assertPersistence(); } public void testSaveErrors() throws Exception { outcome.setErrors(Arrays.<BuildMessageDto>asList( new JdbcBuildMessageDto("an error", null, null, null, BuildMessageType.Error), new JdbcBuildMessageDto("another error", "a bad file", 44, null, BuildMessageType.Error))); assertPersistence(); } public void testSaveErrorsAndWarnings() throws Exception { outcome.setWarnings(Arrays.<BuildMessageDto>asList( new JdbcBuildMessageDto("sample message", "a file", 43, "X12", BuildMessageType.Warning), new JdbcBuildMessageDto("another sample message", "a file", 44, "X13", BuildMessageType.Warning))); outcome.setErrors(Arrays.<BuildMessageDto>asList( new JdbcBuildMessageDto("an error", null, null, null, BuildMessageType.Error), new JdbcBuildMessageDto("another error", "a bad file", 44, null, BuildMessageType.Error))); assertPersistence(); } public void testLoadChecksForExistingBuildLog() throws Exception { outcome.setBuildLogId(outcome.getId()); buildLogExistsFlag = true; assertPersistence(); } public void testLoadChecksForExistingDiff() throws Exception { outcome.setDiffId(outcome.getId()); diffExistsFlag = true; assertPersistence(); } public void testSaveMetrics() throws Exception { final List<MetricDto> metrics = new ArrayList<MetricDto>(); final MetricDto m1 = new MetricDto(); m1.setMessageKey("a.key.of.some.sort"); m1.setValue("0.12"); m1.setType(MetricType.PERCENT); metrics.add(m1); final MetricDto m2 = new MetricDto(); m2.setMessageKey("another.key"); m2.setValue("53"); m2.setType(MetricType.NUMBER); metrics.add(m2); final MetricDto m3 = new MetricDto(); m3.setMessageKey("yet.another.key"); m3.setValue("fifty three"); m3.setType(MetricType.STRING); metrics.add(m3); outcome.setMetrics(metrics); assertPersistence(); } public void testSaveTestFailures() throws Exception { final List<TestFailureDto> list = new ArrayList<TestFailureDto>(); final TestFailureDto tf = new TestFailureDto(); tf.setName("a name of a test"); tf.setBuildNumber(outcome.getBuildNumber()); tf.setMessage("a message"); tf.setDetails("some stack traces"); list.add(tf); outcome.setTestFailures(list); assertPersistence(); } public void testSaveTestFailuresNullMessageAndTrace() throws Exception { final List<TestFailureDto> list = new ArrayList<TestFailureDto>(); final TestFailureDto tf = new TestFailureDto(); tf.setName("a name of a test"); tf.setBuildNumber(outcome.getBuildNumber()); tf.setMessage(null); tf.setDetails(null); list.add(tf); outcome.setTestFailures(list); assertPersistence(); } public void testSaveTestFailuresTruncatesLongMessageAndDetails() throws Exception { final List<TestFailureDto> list = new ArrayList<TestFailureDto>(); final TestFailureDto tf = new TestFailureDto(); tf.setName("a name of a test"); tf.setBuildNumber(outcome.getBuildNumber()); tf.setMessage(StringUtils.repeat("blegh ", JdbcBuildOutcomeStore.MAX_TEST_FAILURE_MESSAGE_LENGTH * 2)); tf.setDetails(StringUtils.repeat("blah ", JdbcBuildOutcomeStore.MAX_TEST_FAILURE_DETAILS_LENGTH * 2)); list.add(tf); outcome.setTestFailures(list); final JdbcBuildOutcomeDto loadedOutcome = storeOutcome(); final TestFailureDto loadedFailure = loadedOutcome.getTestFailures().get(0); assertEquals(JdbcBuildOutcomeStore.MAX_TEST_FAILURE_MESSAGE_LENGTH, loadedFailure.getMessage().length()); assertEquals(JdbcBuildOutcomeStore.MAX_TEST_FAILURE_DETAILS_LENGTH, loadedFailure.getDetails().length()); } public void testSaveCommitLog() throws Exception { final ChangeLogDto log = new ChangeLogDto(); final ChangeSetDto a = new ChangeSetDto(); a.setMessage("did some stuff"); a.setRevisionLabel("1.42"); a.setAuthorName("Jamie"); a.setAuthorEmail("jamie@localhost"); a.setModifiedPaths(Arrays.asList(new ModifiedPathDto("file1", PathModification.Modify), new ModifiedPathDto("file2", null))); final ChangeSetDto b = new ChangeSetDto(); b.setMessage("made some changes"); b.setRevisionLabel("<multiple>"); b.setAuthorName("Barbara"); b.setTimestamp(new Date()); b.setModifiedPaths(Arrays.asList(new ModifiedPathDto("file3", PathModification.Add), new ModifiedPathDto("file4", PathModification.Remove))); log.setChangeSets(Arrays.asList(a, b)); outcome.setChangeLog(log); assertPersistence(); } public void testSaveCommitLogTruncatesLongMessage() throws Exception { final ChangeLogDto log = new ChangeLogDto(); final ChangeSetDto a = new ChangeSetDto(); a.setMessage(StringUtils.repeat("did some stuff", JdbcBuildOutcomeStore.MAX_COMMIT_MESSAGE_LENGTH)); a.setRevisionLabel("1.42"); log.setChangeSets(Arrays.asList(a)); outcome.setChangeLog(log); final JdbcBuildOutcomeDto loadedOutcome = storeOutcome(); final ChangeSetDto change = loadedOutcome.getChangeLog().getChangeSets().get(0); assertEquals(JdbcBuildOutcomeStore.MAX_COMMIT_MESSAGE_LENGTH, change.getMessage().length()); } public void testSaveCommitLogWithFiles() throws Exception { final ChangeLogDto log = new ChangeLogDto(); final ChangeSetDto a = new ChangeSetDto(); a.setMessage("did some stuff"); a.setRevisionLabel("1.42"); a.setModifiedPaths(Arrays.asList(new ModifiedPathDto("a/b/c", PathModification.Modify), new ModifiedPathDto("x/y/z", PathModification.Add))); log.setChangeSets(Arrays.asList(a)); outcome.setChangeLog(log); assertPersistence(); } public void testRenameProjectUpdatesTable() throws Exception { assertPersistence(); store.projectNameChanged(outcome.getName(), "new name"); outcome.setName("new name"); assertPersistence(store.loadBuildOutcome(outcome.getId())); } public void testDoesNotCacheProjectNameOnFailure() throws Exception { store.init(); initCalled = true; outcome.setBuildNumber(null); try { store.storeBuildOutcome(outcome); fail("Expected exception"); } catch (StoreException e) { } dataSource.getConnection().rollback(); outcome.setBuildNumber(33); assertPersistence(); } public void testCountBuildErrors() throws Exception { store.init(); initCalled = true; final BuildOutcomeQueryDto query = new BuildOutcomeQueryDto(); query.setProjectNames(Collections.singleton(outcome.getName())); store.loadTopBuildErrors(query, 5); } public void testAverageBuildTimeNoData() throws Exception { store.init(); initCalled = true; assertEquals(null, store.loadAverageBuildTimeMillis("No such project", UpdateType.Full)); } public void testAverageBuildTime() throws Exception { Long elapsed1 = outcome.getCompletionDate().getTime() - outcome.getStartDate().getTime(); storeOutcome(); outcome.setId(UUID.randomUUID()); outcome.setBuildNumber(outcome.getBuildNumber() + 1); outcome.setStartDate(new Date(outcome.getCompletionDate().getTime() + 10000L)); outcome.setCompletionDate(new Date(outcome.getStartDate().getTime() + 500L)); Long elapsed2 = outcome.getCompletionDate().getTime() - outcome.getStartDate().getTime(); storeOutcome(); Long expected = (elapsed1 + elapsed2) / 2; assertEquals(expected.toString(), store.loadAverageBuildTimeMillis(outcome.getName(), outcome.getUpdateType()).toString()); } public void testHsqldbDateDiffUsesNanosecondsNotMilliseconds() throws Exception { // Seems the meaning of 'ms' changed to nanoseconds in hsqldb 2.0 final Long expected = 1000000000L; // one billion nanoseconds, not one thousand milliseconds final Long actual = new JdbcTemplate(dataSource).queryForLong( "select datediff('ms', CURRENT_TIMESTAMP, dateadd('ss', 1, CURRENT_TIMESTAMP)) from db_version"); assertEquals(expected, actual); } private JdbcBuildOutcomeDto storeOutcome() throws StoreException { if (!initCalled) { store.init(); initCalled = true; } outcome.setPrimaryKey(0); store.storeBuildOutcome(outcome); final JdbcBuildOutcomeDto loadedOutcome = store.loadBuildOutcome(outcome.getId()); return loadedOutcome; } private void assertPersistence() throws StoreException { final JdbcBuildOutcomeDto loadedOutcome = storeOutcome(); assertPersistence(loadedOutcome); } private void assertPersistence(final JdbcBuildOutcomeDto loadedOutcome) { loadedOutcome.setPrimaryKey(0); final String expectedString = outcome.toString().replaceAll("@[^\\[]+", ""); final String actualString = loadedOutcome.toString().replaceAll("@[^\\[]+", ""); if (!expectedString.equals(actualString)) { System.out.println(expectedString); System.out.println(actualString); } assertEquals(expectedString, actualString); } }