package hudson.plugins.testng.results;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.plugins.testng.CommonUtil;
import hudson.plugins.testng.Constants;
import hudson.plugins.testng.PluginImpl;
import hudson.plugins.testng.Publisher;
import hudson.tasks.test.AbstractTestResultAction;
import hudson.tasks.test.TestResult;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestBuilder;
/**
* Tests for {@link ClassResult}'s view page
*
* TODO: speed up the tests by running build once in the setup
*
* @author nullin
*/
public class ClassResultTest {
@Rule
public JenkinsRule r = new JenkinsRule();
/**
* Test using precheckins.legacyops
*
* Verifies:
* 1. multiple testruns show up correctly
* 2. All links show up correctly
* 3. Failures and skips show up correctly
* 4. All cells have a value
* 5. All test runs are unique
*
* @throws Exception
*/
@Test
public void testPrecheckinLegacyOpsClassResults() throws Exception {
FreeStyleProject p = r.createFreeStyleProject();
Publisher publisher = new Publisher();
publisher.setReportFilenamePattern("testng.xml");
publisher.setEscapeTestDescp(false);
publisher.setEscapeExceptionMsg(false);
p.getPublishersList().add(publisher);
p.onCreatedFromScratch(); //to setup project action
p.getBuildersList().add(new TestBuilder() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
String contents = CommonUtil.getContents(Constants.TESTNG_XML_PRECHECKINS);
build.getWorkspace().child("testng.xml").write(contents,"UTF-8");
return true;
}
});
//run build
FreeStyleBuild build = p.scheduleBuild2(0).get();
TestNGResult testngResult = (TestNGResult) build.getAction(AbstractTestResultAction.class).getResult();
TestResult classResult = testngResult.findCorrespondingResult(PluginImpl.URL + "/precheckins/LegacyOps");
Map<String, GroupedTestRun> testRunMap = ((ClassResult)classResult).getTestRunMap();
//Get page
String urlPrefix = build.getUrl() + PluginImpl.URL;
HtmlPage page = r.createWebClient().goTo(urlPrefix + "/precheckins/LegacyOps/");
List<HtmlElement> elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/span[@id='run-info']");
assertEquals(testRunMap.values().size(), elements.size());
Set<String> values = new HashSet<String>(); //will verify that testName|suiteName are not repeated
for (HtmlElement element : elements) {
String content = element.getTextContent();
content = content.replace("(from test '", "");
String testName = content.substring(0, content.indexOf("' in suite '"));
String suiteName = content.replace(testName, "").replace("' in suite '", "");
suiteName = suiteName.substring(0, suiteName.length() - 2); //drop trailing '
boolean found = false;
for (GroupedTestRun groupedTestRun : testRunMap.values()) {
if (groupedTestRun.getSuiteName().equals(suiteName)
&& groupedTestRun.getTestName().equals(testName)) {
found = true;
break;
}
}
assertTrue("Failed to find testname " + testName + " and suitename " + suiteName, found);
values.add(suiteName + "|" + testName);
}
elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/table/*/tr");
assertEquals(6 * (2 + 7), elements.size()); //total number of rows in all tables
elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/table/*/tr/td");
int failCount = 0;
int skipCount = 0;
for (HtmlElement element : elements) {
//none of the cells should be empty
assertNotSame("", element.getTextContent());
if ("FAIL".equals(element.getTextContent())) {
failCount++;
}
if ("SKIP".equals(element.getTextContent())) {
skipCount++;
}
}
assertEquals(1, failCount);
assertEquals(1, skipCount);
//unique set of values for test name and suite name combinations
assertEquals(testRunMap.values().size(), values.size());
//verify all links
elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/table/*/tr/td/a");
List<String> linksInPage = new ArrayList<String>();
for (HtmlElement element : elements) {
linksInPage.add(element.getAttribute("href"));
}
Collections.sort(linksInPage);
List<String> linksFromResult = new ArrayList<String>();
for (MethodResult mr : ((ClassResult) classResult).getChildren()) {
//would have used mr.getUpUrl() but for some reason
//as part of test, Jenkins.instance.rootUrl() returns 'null'
linksFromResult.add(r.getURL() + mr.getRun().getUrl() + mr.getId());
}
Collections.sort(linksFromResult);
assertEquals(linksFromResult, linksInPage);
}
/**
* Test for:
*
* 1. Show more section works correctly
* 2. Case of no config methods is handled correctly
*
* @throws Exception
*/
@Test
public void testClassResults() throws Exception {
FreeStyleProject p = r.createFreeStyleProject();
Publisher publisher = new Publisher();
publisher.setReportFilenamePattern("testng.xml");
publisher.setEscapeTestDescp(false);
publisher.setEscapeExceptionMsg(false);
p.getPublishersList().add(publisher);
p.onCreatedFromScratch(); //to setup project action
p.getBuildersList().add(new TestBuilder() {
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
String contents = CommonUtil.getContents(Constants.TESTNG_XML_TESTNG);
build.getWorkspace().child("testng.xml").write(contents,"UTF-8");
return true;
}
});
//run build
FreeStyleBuild build = p.scheduleBuild2(0).get();
TestNGResult testngResult = (TestNGResult) build.getAction(AbstractTestResultAction.class).getResult();
TestResult classResult = testngResult.findCorrespondingResult(PluginImpl.URL + "/test/CommandLineTest");
Map<String, GroupedTestRun> testRunMap = ((ClassResult)classResult).getTestRunMap();
//Get page
String urlPrefix = build.getUrl() + PluginImpl.URL;
HtmlPage page = r.createWebClient().goTo(urlPrefix + "/test/CommandLineTest");
List<HtmlElement> elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/table[@id='config']");
// there are no configuration methods
assertEquals(0, elements.size());
r.assertStringContains(page.getElementById("run-0").getTextContent(), "No Configuration method was found in this class");
//use first test with show more section
elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/table[@id='test']/tbody/tr/td/div[@id='junitParsing_1']");
assertEquals(1, elements.size());
HtmlElement showMore = elements.get(0);
elements = DomNodeUtil.selectNodes(page, "//div[starts-with(@id, 'run-')]/table[@id='test']/tbody/tr/td/div[@id='junitParsing_2']");
assertEquals(1, elements.size());
HtmlElement moreSection = elements.get(0);
r.assertStringContains(moreSection.getTextContent(), "current"); //group name
//click the link
showMore.getElementsByTagName("a").get(0).click();
r.assertStringContains(showMore.getAttribute("style"), "none");
assertEquals("", moreSection.getAttribute("style"));
}
}