egovframework-dev-tst 프로젝트는 JUnit Test XML 파일을 파싱하고, 템플릿 엑셀 파일을 읽어 들여, 해당값을 매핑한 후 엑셀 형식 리포트로 생성하는 주요 작업을 구성하는 라이브러리이다. 여기에서는 소스 코드에 대한 설명을 하도록 하고, 자세한 내용은 API 문서나 소스를 직접 참조하기 바란다.
<?xml version="1.0" encoding="UTF-8" ?> <testsuite errors="0" skipped="1" tests="6" time="3.359" failures="0" name="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest"> <properties> <property value="Sun Microsystems Inc." name="java.vendor"/> <property value="C:\Documents and Settings\juroh\.m2\repository" name="localRepository"/> . . . . 중략 . . . . </properties> <testcase classname="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest" time="0.594" name="testNonXmlReportFileListException"/> <testcase classname="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest" time="0" name="testNotExistXmlReportFileListException"/> <testcase classname="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest" time="0" name="testNonOutputDirException"/> <testcase classname="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest" time="0" name="testNotExistOutputDirException"/> <testcase classname="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest" time="0.016" name="testGenerateExcelDefault"> <skipped/> </testcase> <testcase classname="egovframework.dev.tst.report.junit.JUnitExcelReportGeneratorTest" time="2.609" name="testGenerateExcelFile"/> </testsuite>
ReportTestCase
는 위 XML에서 <testcase> 태그 정보를 하나씩 담는다.ReportTestSuite
는 위 XML에서 <testsuite> 태그의 요약 정보를 담는다.
JUnit Test XML 파일을 파싱하는 TestSuiteXmlParser
클래스에 대해 알아보자.
TestSuiteXmlParser
클래스는 SAX 파서를 이용하여 XML을 파싱한다. 클래스의 구조는 다음과 같으며, org.xml.sax.helpers.DefaultHandler
클래스의 메소드 중 필요한 부분을 구현하면 된다.
org.xml.sax.helpers.DefaultHandler
를 상속받는다.public class TestSuiteXmlParser extends DefaultHandler { . . . }
Collection parse(String xmlPath)
ReportTestCase
와 ReportTestSuite
객체에 정보를 담는다. JUnitReportParser
가 호출한다. public Collection parse(String xmlPath) throws ParserConfigurationException, SAXException, IOException { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); classesToSuites = new HashMap(); saxParser.parse(new File(xmlPath), this); if (currentSuite != defaultSuite) { // defaultSuite if (defaultSuite.getNumberOfTests() == 0){ classesToSuites.remove(defaultSuite.getFullClassName()); } } return classesToSuites.values(); }
✔ 사용 예는 TestCase(TestSuiteXmlParserTest
)를 통해 확인할 수 있다.
void startElement(String uri, String localName, String qName, Attributes attributes)
: 시작 태그에 대한 처리 부분을 담고 있다.void endElement(String uri, String localName, String qName)
: 끝 태그에 대한 처리 부분을 담고 있다.void characters(char ch[], int start, int length)
: element 내의 문자 데이터 처리에 대한 로직private List parseCause(String detail)
: Fail 원인에 대한 처리를 위해 내부적으로 사용하는 메소드private List parseCause(String detail, String compareTo)
: Fail 원인에 대한 처리를 위해 내부적으로 사용하는 메소드
JUnitReportParser
는 파싱한 XML 정보를 담고 있는 ReportTestCase
와 ReportTestSuite
을 이용하여 리포팅에 필요한 정보로 재조정한다.
JUnit Test XML 파일 Full Path 목록과, TestSuite List를 사용한다.
/** JUnit Test XML 파일 Full Path 목록 */ List<File> xmlReportFileList; /** TestSuite 목록 */ List<ReportTestSuite> testSuites = new ArrayList<ReportTestSuite>();
List parseXMLReportFiles()
- JUnit Test XML 파일을 파싱하는 메인 함수 public List parseXMLReportFiles() throws EgovTestException { Collection suites = null; if (xmlReportFileList != null && xmlReportFileList.size() > 0) { TestSuiteXmlParser parser = new TestSuiteXmlParser(); for (int idx = 0; idx < xmlReportFileList.size(); idx++) { File currentReport = (File) xmlReportFileList.get(idx); try { suites = parser.parse(currentReport.getAbsolutePath()); } catch (. . .) { . . .} testSuites.addAll(suites); } } return testSuites; }
✔ 사용 예는 TestCase(JUnitReportParserTest
)에서 확인할 수 있다.
Map getSummary(List suites)
: ReportTestSuite
으로부터 전체 Summary 정보를 모은다.Map getSuitesGroupByPackage(List testSuitesList)
: ReportTestSuite
으로부터 패키지별 요약 정보를 모은다. computeSuccessRate(int tests, int errors, int failures, int skipped)
: 성공률을 백분률로 계산한다./** JUnit XML Parser */ private JUnitReportParser parser; /** JUnit Test XML 파일 Full Path 목록 */ List<File> xmlReportFileList; /** Test Suite Lists */ private List<ReportTestSuite> testSuites;
/** ExtenXLS object representing MS Excel Document */ private HSSFWorkbook book;
/** Summary 헤더 위치 정보 */ private int[] summaryPosInfos = { 0, 0, 3 }; // sheet, col, row /** Package 헤더 위치 정보 */ private int[] packagePosInfos = { 0, 0, 7 }; // sheet, col, row /** TestCase Lists 헤더 위치 정보 */ private int[] listsPosInfos = { 1, 0, 3 }; // sheet, row, col
/** Sheet 정보 IDX_SHEET */ public final static int IDX_SHEET = 0; /** Column 정보 IDX_COL */ public final static int IDX_COL = 1; /** Row 정보 IDX_ROW */ public final static int IDX_ROW = 2;
생성자에서 입력 받아야 하는 정보는 다음과 같다.
/** * 생성자 * * @param xmlReportFileList JUnit Test XML 파일의 Full Path List */ public EgovJUnitExcelReportGenerator(List<File> xmlReportFileList) { this.xmlReportFileList = xmlReportFileList; } /** * 생성자 * * @param xmlReportFileList JUnit Test XML 파일의 Full Path List * @param templatePath 템플릿 엑셀 파일 객체 * @param outputDirectory 파일 생성 위치 객체 * @param outputName 생성될 엑셀 파일 명 */ public EgovJUnitExcelReportGenerator(List<File> xmlReportFileList, File templatePath, File outputDirectory, String outputName) { this.xmlReportFileList = xmlReportFileList; this.templatePath = templatePath; this.outputDirectory = outputDirectory; this.outputName = outputName; }
템플릿 엑셀 파일을 읽어 Workbook을 생성하는 방법은 EgovExcelUtil
클래스의 readExcelFile
메소드에서 담당한다.
public static HSSFWorkbook readExcelFile(File xlsFullPath) throws EgovTestException { POIFSFileSystem fs = null; // POI FileSystem HSSFWorkbook wb = null; // HSSFWorkbook 엑셀 Workbook try { FileInputStream fis = new FileInputStream(xlsFullPath); fs = new POIFSFileSystem(fis); wb = new HSSFWorkbook(fs); } catch (...) { . . . } return wb; }
엑셀 파일로 저장하는 기능은 writeExcelReport
메소드에서 담당한다.
public static void writeExcelReport(File fullPath, HSSFWorkbook wb) { FileOutputStream fos = null; try { fos = new FileOutputStream(fullPath); wb.write(fos); fos.close(); } catch (...) { . . . } }
Cell은 엑셀 파일의 Sheet 내에서 column과 row 값을 갖는 단위를 말한다. Cell에 값을 세팅하는 기능은 setCellValues
에서 담당한다.
public static void setCellValues(HSSFRow row, List values, int startColumn, HSSFRow startRow) { HSSFCellStyle style = null; HSSFCell cell = null; HSSFCell startCell = null; int currentColumn = startColumn; for (int index = 0; index < values.size(); index++) { cell = row.getCell(currentColumn); if (cell == null) { cell = row.createCell(currentColumn); } setCellValue(cell, values.get(index)); // Style을 세팅한다. if (startRow != null) { startCell = startRow.getCell(currentColumn); if (startCell != null) { style = startCell.getCellStyle(); cell.setCellStyle(style); } } currentColumn++; } } public static void setCellValues(HSSFRow row, int currentCol, Object value) { HSSFCell cell = null; if (value != null) { cell = row.getCell(currentCol); if (cell == null) { cell = row.createCell(currentCol); } setCellValue(cell, value); } } public static void setCellValue(HSSFCell cell, Object value) { if (value != null) { if (value instanceof String) { cell.setCellValue(new HSSFRichTextString((String) value)); } else if (value instanceof Integer) { cell.setCellValue((Integer) value); } else if (value instanceof Double) { cell.setCellValue((Double) value); } else if (value instanceof Float) { cell.setCellValue((Float) value); } } }