Package hudson.tasks.junit

Source Code of hudson.tasks.junit.TestResultPublishingTest

/*
* The MIT License
*
* Copyright (c) 2009, 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 com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.html.*;
import com.gargoylesoftware.htmlunit.xml.XmlPage;
import hudson.FilePath;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.Project;
import hudson.model.Run;
import hudson.slaves.DumbSlave;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.TouchBuilder;
import org.jvnet.hudson.test.recipes.LocalData;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class TestResultPublishingTest extends HudsonTestCase {
    private FreeStyleProject project;
    private JUnitResultArchiver archiver;
    private final String BASIC_TEST_PROJECT = "percival";
    private final String TEST_PROJECT_WITH_HISTORY = "wonky";


    @Override
    protected void setUp() throws Exception {
        super.setUp();
        project = createFreeStyleProject(BASIC_TEST_PROJECT);
        archiver = new JUnitResultArchiver("*.xml");
        project.getPublishersList().add(archiver);
        project.getBuildersList().add(new TouchBuilder());
    }

    @LocalData
    public void testBasic() throws Exception {
        FreeStyleBuild build = project.scheduleBuild2(0).get(30, TimeUnit.SECONDS);

        assertTestResults(build);

        HudsonTestCase.WebClient wc = new HudsonTestCase.WebClient();
        wc.getPage(project); // project page
        wc.getPage(build); // build page
        wc.getPage(build, "testReport")// test report
        wc.getPage(build, "testReport/hudson.security"); // package
        wc.getPage(build, "testReport/hudson.security/HudsonPrivateSecurityRealmTest/"); // class
        wc.getPage(build, "testReport/hudson.security/HudsonPrivateSecurityRealmTest/testDataCompatibilityWith1_282/"); // method
    }


    @LocalData
    public void testSlave() throws Exception {
        DumbSlave s = createOnlineSlave();
        project.setAssignedLabel(s.getSelfLabel());

        FilePath src = new FilePath(hudson.getRootPath(), "jobs/" + BASIC_TEST_PROJECT + "/workspace/");
        assertNotNull(src);
        FilePath dest = s.getWorkspaceFor(project);
        assertNotNull(dest);
        src.copyRecursiveTo("*.xml", dest);

        testBasic();
    }
 

    /**
     * Verify that we can successfully parse and display test results in the
     * open junit test result publishing toolchain. Ensure that we meet this
     * compatibility requirement:
     * From users' point of view, Hudson core JUnit should continue
     * to work as if nothing has changed
     * - Old testReport URLs should still work
     */
    @LocalData
    public void testOpenJUnitPublishing() throws IOException, SAXException {
        List<Project> projects = this.hudson.getProjects();
        // Make sure there's a project named TEST_PROJECT_WITH_HISTORY
        Project proj = null;
        for (Project p : projects) {
            if (p.getName().equals(TEST_PROJECT_WITH_HISTORY)) proj = p;
        }
        assertNotNull("We should have a project named " + TEST_PROJECT_WITH_HISTORY, proj);

        // Validate that there are test results where I expect them to be:
        HudsonTestCase.WebClient wc = new HudsonTestCase.WebClient();

        // On the project page:
        HtmlPage projectPage = wc.getPage(proj);
        //      we should have a link that reads "Latest Test Result"
        //      that link should go to http://localhost:8080/job/breakable/lastBuild/testReport/
        assertXPath(projectPage, "//a[@href='lastCompletedBuild/testReport/']");
        assertXPathValue(projectPage, "//a[@href='lastCompletedBuild/testReport/']", "Latest Test Result");
        assertXPathValueContains(projectPage, "//a[@href='lastCompletedBuild/testReport/']", "Latest Test Result");
        //      after "Latest Test Result" it should say "no failures"
        assertXPathResultsContainText(projectPage, "//td", "(no failures)");
        //      there should be a test result trend graph
        assertXPath(projectPage, "//img[@src='test/trend']");
        // the trend graph should be served up with a good http status
        Page trendGraphPage = wc.goTo(proj.getUrl() + "/test/trend", "image/png");
        assertGoodStatus(trendGraphPage);

        // The trend graph should be clickable and take us to a run details page
        Object imageNode = projectPage.getFirstByXPath("//img[@src='test/trend']");
        assertNotNull("couldn't find any matching nodes", imageNode);
        assertTrue("image node should be an HtmlImage object", imageNode instanceof HtmlImage);
        // TODO: Check that we can click on the graph and get to a particular run. How do I do this with HtmlUnit?

        XmlPage xmlProjectPage = wc.goToXml(proj.getUrl() + "/lastBuild/testReport/api/xml");
        assertXPath(xmlProjectPage, "/testResult");
        assertXPath(xmlProjectPage, "/testResult/suite");
        assertXPath(xmlProjectPage, "/testResult/failCount");
        assertXPathValue(xmlProjectPage, "/testResult/failCount", "0");
        assertXPathValue(xmlProjectPage, "/testResult/passCount", "4");
        assertXPathValue(xmlProjectPage, "/testResult/skipCount", "0");
        String[] packages = {"org.jvnet.hudson.examples.small.AppTest", "org.jvnet.hudson.examples.small.MiscTest", "org.jvnet.hudson.examples.small.deep.DeepTest"};
        for (String packageName : packages) {
            assertXPath(xmlProjectPage, "/testResult/suite/case/className[text()='" + packageName + "']");
        }

        // Go to a page that we know has a failure
        HtmlPage buildPage = wc.getPage(proj.getBuildByNumber(3));
        assertGoodStatus(buildPage);
        // We expect to see one failure, for com.yahoo.breakable.misc.UglyTest.becomeUglier
        // which should link to http://localhost:8080/job/wonky/3/testReport/org.jvnet.hudson.examples.small/MiscTest/testEleanor/
        assertXPathResultsContainText(buildPage, "//a", "org.jvnet.hudson.examples.small.MiscTest.testEleanor");
        HtmlAnchor failingTestLink = buildPage.getFirstAnchorByText("org.jvnet.hudson.examples.small.MiscTest.testEleanor");
        assertNotNull(failingTestLink);
        Page failingTestPage = failingTestLink.click();
        assertGoodStatus(failingTestPage);

        // Go to the xml page for a build we know has failures
        XmlPage xmlBuildPage = wc.goToXml(proj.getBuildByNumber(3).getUrl() + "/api/xml");
        assertXPathValue(xmlBuildPage, "//failCount", "2");
        assertXPathValue(xmlBuildPage, "//skipCount", "0");
        assertXPathValue(xmlBuildPage, "//totalCount", "4");
        assertXPathValue(xmlBuildPage, "//result", "FAILURE");

        // Check overall test result counts
        XmlPage xmlTestReportPage = wc.goToXml(proj.getBuildByNumber(3).getUrl() + "/testReport/api/xml");
        assertXPathValue(xmlTestReportPage, "/testResult/failCount", "2");
        assertXPathValue(xmlTestReportPage, "/testResult/passCount", "2");
        assertXPathValue(xmlTestReportPage, "/testResult/skipCount", "0");

        // Make sure the right tests passed and failed
        assertXPathValue(xmlTestReportPage, "/testResult/suite/case[className/text()='org.jvnet.hudson.examples.small.AppTest']/status", "PASSED");
        assertXPathValue(xmlTestReportPage, "/testResult/suite/case[name/text()='testEleanor']/status", "FAILED");


        // TODO: implement more of these tests
        // On the lastBuild/testReport page:
        //      Breadcrumbs should read #6 > Test Result  where Test Result is a link to this page
        //      inside of div id="main-panel" we should find the text "0 failures (-1)"
        //      we should have a blue bar which is blue all the way across: div style="width: 100%; height: 1em; background-color: rgb(114, 159, 207);
        //      we should find the words "7 tests (?0)"
        //      we should find the words "All Tests"
        //      we should find a table

        //      Inside that table, there should be the following rows:
        //           org.jvnet.hudson.examples.small   0ms   0 -1 0   3
        //          org.jvnet.hudson.examples.small.deep   4ms 0 0 0  1
        Run theRun = proj.getBuildByNumber(7);
        assertTestResultsAsExpected(wc, theRun, "/testReport",
                "org.jvnet.hudson.examples.small", "0 ms", "SUCCESS",
                /* total tests expected, diff */ 3, 0,
                /* fail count expected, diff */ 0, -1,
                /* skip count expected, diff */ 0, 0);

        assertTestResultsAsExpected(wc, theRun, "/testReport",
                "org.jvnet.hudson.examples.small.deep", "4 ms", "SUCCESS",
                /* total tests expected, diff */ 1, 0,
                /* fail count expected, diff */ 0, 0,
                /* skip count expected, diff */ 0, 0);

        // TODO: more, more, more.
        // TODO: test report history by package

    }

    /**
     * Test to demonstrate bug HUDSON-5246, inter-build diffs for junit test results are wrong
     */
    @Bug(5246)
    @LocalData
    public void testInterBuildDiffs() throws IOException, SAXException {
        List<Project> projects = this.hudson.getProjects();
        // Make sure there's a project named TEST_PROJECT_WITH_HISTORY
        Project proj = null;
        for (Project p : projects) {
            if (p.getName().equals(TEST_PROJECT_WITH_HISTORY)) proj = p;
        }
        assertNotNull("We should have a project named " + TEST_PROJECT_WITH_HISTORY, proj);

        // Validate that there are test results where I expect them to be:
        HudsonTestCase.WebClient wc = new HudsonTestCase.WebClient();
        Run theRun = proj.getBuildByNumber(4);
        assertTestResultsAsExpected(wc, theRun, "/testReport",
                        "org.jvnet.hudson.examples.small", "12 ms", "FAILURE",
                        /* total tests expected, diff */ 3, 0,
                        /* fail count expected, diff */ 1, 0,
                        /* skip count expected, diff */ 0, 0);


    }

    /**
     * Make sure the open junit publisher shows junit history
     * @throws IOException
     * @throws SAXException
     */
    @LocalData
    public void testHistoryPageOpenJunit() throws IOException, SAXException {
        List<Project> projects = this.hudson.getProjects();
        // Make sure there's a project named breakable
        Project proj = null;
        for (Project p : projects) {
            if (p.getName().equals(TEST_PROJECT_WITH_HISTORY)) {
                proj = p;
                break;
            }
        }
        assertNotNull("We should have a project named " + TEST_PROJECT_WITH_HISTORY, proj);

        // Validate that there are test results where I expect them to be:
        HudsonTestCase.WebClient wc = new HudsonTestCase.WebClient();

        HtmlPage historyPage = wc.getPage(proj.getBuildByNumber(7),"/testReport/history/");
        assertGoodStatus(historyPage);
        assertXPath(historyPage, "//img[@id='graph']");
        assertXPath(historyPage, "//table[@id='testresult']");
        HtmlElement wholeTable = historyPage.getElementById("testresult");
        assertNotNull("table with id 'testresult' exists", wholeTable);
        assertTrue("wholeTable is a table", wholeTable instanceof HtmlTable);
        HtmlTable table = (HtmlTable) wholeTable;

        // We really want to call table.getRowCount(), but
        // it returns 1, not the real answer,
        // because this table has *two* tbody elements,
        // and getRowCount() only seems to count the *first* tbody.
        // Maybe HtmlUnit can't handle the two tbody's. In any case,
        // the tableText.contains tests do a (ahem) passable job
        // of detecting whether the history results are present.

        String tableText = table.getTextContent();
        assertTrue("Table text is missing the project name",
                tableText.contains(TEST_PROJECT_WITH_HISTORY));
        assertTrue("Table text is missing the build number",
                tableText.contains("7"));
        assertTrue("Table text is missing the test duration",
                tableText.contains("4 ms"));
    }


 
    void assertStringEmptyOrNull(String msg, String str) {
        if (str==null)
            return;
        if (str.equals(""))
            return;
        fail(msg + "(should be empty or null) : \'" + str + "\'");
    }

    void assertPaneDiffText(String msg, int expectedValue, Object paneObj) {
        assertTrue( "paneObj should be an HtmlElement", paneObj instanceof HtmlElement );
        String paneText = ((HtmlElement) paneObj).asText();
        if (expectedValue==0) {
            assertStringEmptyOrNull(msg, paneText);
        } else {
            String expectedString =
             (expectedValue >= 1 ? "+" : "-")
                    + Math.abs(expectedValue);
            assertEquals(msg, expectedString, paneText);
        }
    }

    void assertTestResultsAsExpected(WebClient wc, Run run, String restOfUrl,
                                     String packageName,
                                     String expectedResult, String expectedDurationStr,
                                     int expectedTotalTests, int expectedTotalDiff,
                                     int expectedFailCount, int expectedFailDiff,
                                     int expectedSkipCount, int expectedSkipDiff) throws IOException, SAXException {

        // TODO: verify expectedResult
        // TODO: verify expectedDuration

        XmlPage xmlPage = wc.goToXml(run.getUrl() + restOfUrl + "/" + packageName + "/api/xml");
        int expectedPassCount = expectedTotalTests - expectedFailCount - expectedSkipCount;
        // Verify xml results
        assertXPathValue(xmlPage, "/packageResult/failCount", Integer.toString(expectedFailCount));
        assertXPathValue(xmlPage, "/packageResult/skipCount", Integer.toString(expectedSkipCount));
        assertXPathValue(xmlPage, "/packageResult/passCount", Integer.toString(expectedPassCount));
        assertXPathValue(xmlPage, "/packageResult/name", packageName);

        // TODO: verify html results
        HtmlPage testResultPage =   wc.getPage(run, restOfUrl);

        // Verify inter-build diffs in html table
        String xpathToFailDiff =  "//table[@id='testresult']//tr[td//span[text()=\"" + packageName + "\"]]/td[4]";
        String xpathToSkipDiff =  "//table[@id='testresult']//tr[td//span[text()=\"" + packageName + "\"]]/td[6]";
        String xpathToTotalDiff = "//table[@id='testresult']//tr[td//span[text()=\"" + packageName + "\"]]/td[last()]";

        Object totalDiffObj = testResultPage.getFirstByXPath(xpathToTotalDiff);
        assertPaneDiffText("total diff", expectedTotalDiff, totalDiffObj);

        Object failDiffObj = testResultPage.getFirstByXPath(xpathToFailDiff);
        assertPaneDiffText("failure diff", expectedFailDiff, failDiffObj);

        Object skipDiffObj = testResultPage.getFirstByXPath(xpathToSkipDiff);
        assertPaneDiffText("skip diff", expectedSkipDiff, skipDiffObj);

        // TODO: The link in the table for each of the three packages in the testReport table should link to a by-package page,
        // TODO: for example, http://localhost:8080/job/breakable/lastBuild/testReport/com.yahoo.breakable.misc/

    }

    // TODO: Make sure that we meet this compatibility requirement:
    // TODO: From users' point of view, Open Source  *Unit publishers should continue to work as if nothing has changed
    // TODO: * Old testReport URLs should still work


    private void assertTestResults(FreeStyleBuild build) {
        TestResultAction testResultAction = build.getAction(TestResultAction.class);
        assertNotNull("no TestResultAction", testResultAction);

        TestResult result = testResultAction.getResult();
        assertNotNull("no TestResult", result);

        assertEquals("should have 1 failing test", 1, testResultAction.getFailCount());
        assertEquals("should have 1 failing test", 1, result.getFailCount());

        assertEquals("should have 132 total tests", 132, testResultAction.getTotalCount());
        assertEquals("should have 132 total tests", 132, result.getTotalCount());
    }

}
TOP

Related Classes of hudson.tasks.junit.TestResultPublishingTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.