/* * The MIT License * * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Yahoo! Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package hudson.tasks.junit; import hudson.model.FreeStyleProject; import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.model.Result; import hudson.model.FreeStyleBuild; import hudson.maven.MavenModuleSet; import hudson.maven.MavenModuleSetBuild; import hudson.maven.MavenBuild; import hudson.maven.reporters.SurefireReport; import hudson.Launcher; import org.jvnet.hudson.test.HudsonTestCase; import org.jvnet.hudson.test.Email; import org.jvnet.hudson.test.Bug; import org.jvnet.hudson.test.TestBuilder; import org.jvnet.hudson.test.ExtractResourceSCM; import com.gargoylesoftware.htmlunit.html.HtmlPage; import com.gargoylesoftware.htmlunit.html.HtmlElement; import com.gargoylesoftware.htmlunit.xml.XmlPage; import java.io.IOException; /** * @author Kohsuke Kawaguchi */ public class CaseResultTest extends HudsonTestCase { // /** // * Verifies that Hudson can capture the stdout/stderr output from Maven surefire. // */ // public void testSurefireOutput() throws Exception { // setJavaNetCredential(); // configureDefaultMaven(); // // MavenModuleSet p = createMavenProject(); // p.setScm(new SubversionSCM("https://svn.dev.java.net/svn/hudson/trunk/hudson/test-projects/junit-failure@16411")); // MavenModuleSetBuild b = assertBuildStatus(UNSTABLE,p.scheduleBuild2(0).get()); // AbstractTestResultAction<?> t = b.getTestResultAction(); // assertSame(1,t.getFailCount()); // CaseResult tc = t.getFailedTests().get(0); // assertTrue(tc.getStderr().contains("stderr")); // assertTrue(tc.getStdout().contains("stdout")); // } @Email("http://www.nabble.com/NPE-%28Fatal%3A-Null%29-in-recording-junit-test-results-td23562964.html") public void testIssue20090516() throws Exception { FreeStyleBuild b = configureTestBuild(null); TestResult tr = b.getAction(TestResultAction.class).getResult(); assertEquals(3,tr.getFailedTests().size()); CaseResult cr = tr.getFailedTests().get(0); assertEquals("org.twia.vendor.VendorManagerTest",cr.getClassName()); assertEquals("testGetVendorFirmKeyForVendorRep",cr.getName()); // piggy back tests for annotate methods assertOutput(cr,"plain text", "plain text"); assertOutput(cr,"line #1\nhttp://nowhere.net/\nline #2\n", "line #1\n<a href=\"http://nowhere.net/\">http://nowhere.net/</a>\nline #2\n"); assertOutput(cr,"failed; see http://nowhere.net/", "failed; see <a href=\"http://nowhere.net/\">http://nowhere.net/</a>"); assertOutput(cr,"failed (see http://nowhere.net/)", "failed (see <a href=\"http://nowhere.net/\">http://nowhere.net/</a>)"); assertOutput(cr,"http://nowhere.net/ - failed: http://elsewhere.net/", "<a href=\"http://nowhere.net/\">http://nowhere.net/</a> - failed: " + "<a href=\"http://elsewhere.net/\">http://elsewhere.net/</a>"); assertOutput(cr,"https://nowhere.net/", "<a href=\"https://nowhere.net/\">https://nowhere.net/</a>"); assertOutput(cr,"stuffhttp://nowhere.net/", "stuffhttp://nowhere.net/"); assertOutput(cr,"a < b && c < d", "a < b && c < d"); assertOutput(cr,"see <http://nowhere.net/>", "see <<a href=\"http://nowhere.net/\">http://nowhere.net/</a>>"); assertOutput(cr,"http://google.com/?q=stuff&lang=en", "<a href=\"http://google.com/?q=stuff&lang=en\">http://google.com/?q=stuff&lang=en</a>"); assertOutput(cr,"http://localhost:8080/stuff/", "<a href=\"http://localhost:8080/stuff/\">http://localhost:8080/stuff/</a>"); } /** * Verifies that the error message and stacktrace from a failed junit test actually render properly. */ @Bug(4257) public void testFreestyleErrorMsgAndStacktraceRender() throws Exception { FreeStyleBuild b = configureTestBuild("render-test"); TestResult tr = b.getAction(TestResultAction.class).getResult(); assertEquals(3,tr.getFailedTests().size()); CaseResult cr = tr.getFailedTests().get(1); assertEquals("org.twia.vendor.VendorManagerTest",cr.getClassName()); assertEquals("testGetRevokedClaimsForAdjustingFirm",cr.getName()); assertNotNull("Error details should not be null", cr.getErrorDetails()); assertNotNull("Error stacktrace should not be null", cr.getErrorStackTrace()); String testUrl = cr.getRelativePathFrom(tr); HtmlPage page = new WebClient().goTo("job/render-test/1/testReport/" + testUrl); HtmlElement errorMsg = (HtmlElement) page.getByXPath("//h3[text()='Error Message']/following-sibling::*").get(0); assertEquals(cr.annotate(cr.getErrorDetails()).replaceAll("<", "<"), errorMsg.getTextContent()); HtmlElement errorStackTrace = (HtmlElement) page.getByXPath("//h3[text()='Stacktrace']/following-sibling::*").get(0); // Have to do some annoying replacing here to get the same text Jelly produces in the end. assertEquals(cr.annotate(cr.getErrorStackTrace()).replaceAll("<", "<").replace("\r\n", "\n"), errorStackTrace.getTextContent()); } /** * Verifies that the error message and stacktrace from a failed junit test actually render properly. */ @Bug(4257) public void testMavenErrorMsgAndStacktraceRender() throws Exception { configureDefaultMaven(); MavenModuleSet m = createMavenProject("maven-render-test"); m.setScm(new ExtractResourceSCM(m.getClass().getResource("maven-test-failure-findbugs.zip"))); m.setGoals("clean test"); MavenModuleSetBuild b = assertBuildStatus(Result.UNSTABLE, m.scheduleBuild2(0).get()); MavenBuild modBuild = (MavenBuild)b.getModuleLastBuilds().get(m.getModule("test:test")); TestResult tr = modBuild.getAction(SurefireReport.class).getResult(); assertEquals(1,tr.getFailedTests().size()); CaseResult cr = tr.getFailedTests().get(0); assertEquals("test.AppTest",cr.getClassName()); assertEquals("testApp",cr.getName()); assertNotNull("Error details should not be null", cr.getErrorDetails()); assertNotNull("Error stacktrace should not be null", cr.getErrorStackTrace()); } /** * Verify fields show up at the correct visibility in the remote API */ private static final String[] MAX_VISIBILITY_FIELDS = { "name" }; private static final String[] REDUCED_VISIBILITY_FIELDS = { "stdout", "stderr", "errorStackTrace", "errorDetails" }; private static final String[] OTHER_FIELDS = { "duration", "className", "failedSince", "age", "skipped", "status" }; @Email("http://www.nabble.com/Change-remote-API-visibility-for-CaseResult.getStdout-getStderr-td25619046.html") public void testRemoteApiDefaultVisibility() throws Exception { FreeStyleBuild b = configureTestBuild("test-remoteapi"); XmlPage page = (XmlPage) new WebClient().goTo("job/test-remoteapi/1/testReport/org.twia.vendor/VendorManagerTest/testCreateAdjustingFirm/api/xml","application/xml"); int found = 0; found = page.getByXPath(composeXPath(MAX_VISIBILITY_FIELDS)).size(); assertTrue("Should have found an element, but found " + found, found > 0); found = page.getByXPath(composeXPath(REDUCED_VISIBILITY_FIELDS)).size(); assertTrue("Should have found an element, but found " + found, found > 0); found = page.getByXPath(composeXPath(OTHER_FIELDS)).size(); assertTrue("Should have found an element, but found " + found, found > 0); } @Email("http://www.nabble.com/Change-remote-API-visibility-for-CaseResult.getStdout-getStderr-td25619046.html") public void testRemoteApiNoDetails() throws Exception { FreeStyleBuild b = configureTestBuild("test-remoteapi"); XmlPage page = (XmlPage) new WebClient().goTo("job/test-remoteapi/1/testReport/org.twia.vendor/VendorManagerTest/testCreateAdjustingFirm/api/xml?depth=-1","application/xml"); int found = 0; found = page.getByXPath(composeXPath(MAX_VISIBILITY_FIELDS)).size(); assertTrue("Should have found an element, but found " + found, found > 0); found = page.getByXPath(composeXPath(REDUCED_VISIBILITY_FIELDS)).size(); assertTrue("Should have found 0 elements, but found " + found, found == 0); found = page.getByXPath(composeXPath(OTHER_FIELDS)).size(); assertTrue("Should have found an element, but found " + found, found > 0); } @Email("http://www.nabble.com/Change-remote-API-visibility-for-CaseResult.getStdout-getStderr-td25619046.html") public void testRemoteApiNameOnly() throws Exception { FreeStyleBuild b = configureTestBuild("test-remoteapi"); XmlPage page = (XmlPage) new WebClient().goTo("job/test-remoteapi/1/testReport/org.twia.vendor/VendorManagerTest/testCreateAdjustingFirm/api/xml?depth=-10","application/xml"); int found = 0; found = page.getByXPath(composeXPath(MAX_VISIBILITY_FIELDS)).size(); assertTrue("Should have found an element, but found " + found, found > 0); found = page.getByXPath(composeXPath(REDUCED_VISIBILITY_FIELDS)).size(); assertTrue("Should have found 0 elements, but found " + found, found == 0); found = page.getByXPath(composeXPath(OTHER_FIELDS)).size(); assertTrue("Should have found 0 elements, but found " + found, found == 0); } private FreeStyleBuild configureTestBuild(String projectName) throws Exception { FreeStyleProject p = projectName == null ? createFreeStyleProject() : createFreeStyleProject(projectName); p.getBuildersList().add(new TestBuilder() { public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { build.getWorkspace().child("junit.xml").copyFrom( getClass().getResource("junit-report-20090516.xml")); return true; } }); p.getPublishersList().add(new JUnitResultArchiver("*.xml")); return assertBuildStatus(Result.UNSTABLE, p.scheduleBuild2(0).get()); } private String composeXPath(String[] fields) throws Exception { StringBuilder tmp = new StringBuilder(100); for ( String f : fields ) { if (tmp.length() > 0 ) { tmp.append("|"); } tmp.append("//caseResult/"); tmp.append(f); } return tmp.toString(); } private void assertOutput(CaseResult cr, String in, String out) throws Exception { assertEquals(out, cr.annotate(in)); } }