6.2.2 result.jsp
result.jsp从configuration.jsp获取索引的路径,将其作为参数创建IndexSearcher对象。result.jsp将index.jsp提交请求中的查询条件参数传递给QueryParser对象解析。完成IndexSearcher对象和QueryParser对象的构造后,result.jsp开始执行查询,并将查询后的结果根据分页设置展现出来。
本项目中,result.jsp代码(代码6.3)中包含了表现层的所有逻辑。由于JSP代码存在的
单元测试难点,不论哪一种测试方案都显得不够完善。鉴于本项目表现层功能清晰简易的特点,对result.jsp的测试方案倾向于兼顾功能点覆盖和代码覆盖。
代码6.3 result.jsp
<%@ page import = " javax.servlet.*, javax.servlet.http.*, java.io.*, org.apache.lucene.analysis.*, org.apache.lucene.analysis.standard.StandardAnalyzer, org.apache.lucene.document.*, org.apache.lucene.index.*, org.apache.lucene.search.*, org.apache.lucene.queryParser.*, org.apache.lucene.demo.*, org.apache.lucene.demo. html.Entities, java.net.URLEncoder" %> 002 003 <% 004 /* 005 Author: Andrew C. Oliver, SuperLink Software, Inc. (acoliver2@users. sourceforge.net) 006 007 This jsp page is deliberatly written in the horrible java directly embedded 008 in the page style for an easy and concise demonstration of Lucene. 009 Due note...if you write pages that look like this...sooner or later 010 you'll have a maintenance nightmare. If you use jsps...use taglibs 011 and beans! That being said, this should be acceptable for a small 012 page demonstrating how one uses Lucene in a web app. 013 014 This is also deliberately overcommented. ;-) 015 016 */ 017 %> 018 <%! 019 public String escapeHTML(String s) { 020 s = s.replaceAll("&", "&"); 021 s = s.replaceAll("<", "<"); 022 s = s.replaceAll(">", ">"); 023 s = s.replaceAll("\"", """); 024 s = s.replaceAll("'", "'"); 025 return s; 026 } 027 %> 028 <%@includefile="header.jsp"%> 029 <% 030 boolean error = false; //used to control flow for error messages 031 String indexName = indexLocation; //local copy of the configuration variable 032 IndexSearcher searcher = null; //the searcher used to open/search the index 033 Query query = null; //the Query created by the QueryParser 034 Hits hits = null; //the search results 035 int startindex = 0; //the first index displayed on this page 036 int maxpage = 50; //the maximum items displayed on this page 037 String queryString = null; //the query entered in the previous page 038 String startVal = null; //string version of startindex 039 String maxresults = null; //string version of maxpage 040 int thispage = 0; //used for the for/next either maxpage or 041 //hits.length() - startindex - whichever is 042 //less 043 044 try { 045 searcher = new IndexSearcher(indexName);//create an indexSearcher for our page 046 //NOTE: this operation is slow for large 047 //indices (much slower than the search itself) 048 //so you might want to keep an IndexSearcher 049 //open 050 051 } catch (Exception e) { //any error that happens is probably due 052 //to a permission problem or non-existant 053 //or otherwise corrupt index 054 %> 055 <p>ERROR opening the Index - contact sysadmin!</p> 056 <p>Error message: <%=escapeHTML(e.getMessage())%></p> 057 <% error = true; //don't do anything up to the footer 058 } 059 %> 060 <% 061 if (error == false) { //did we open the index? 062 queryString = request.getParameter("query"); //get the search criteria 063 startVal = request.getParameter("startat"); //get the start index 064 maxresults = request.getParameter("maxresults"); //get max results per page 065 try { 066 maxpage = Integer.parseInt(maxresults);//parse the max results first 067 startindex = Integer.parseInt(startVal); //then the start index 068 } catch (Exception e) { } //we don't care if something happens we'll 069 //just start at 0or end at 50 070 071 072 073 if (queryString == null) 074 throw new ServletException("no query "+ //if you don't have a query then 075 "specified"); //you probably played on the 076 //query string so you get the 077 //treatment 078 079 Analyzer analyzer = new StandardAnalyzer(); //construct our usual 080 try { //analyzer 081 QueryParser qp = new QueryParser("contents", analyzer); 082 query = qp.parse(queryString); //parse the query and 083 } catch (ParseException e) { //construct the Query 084 //object 085 //if it's just "operator error" 086 //send them a nice error HTML 087 088 %> 089 <p>Error while parsing query: <%=escapeHTML(e.get Message())%></p> 090 <% 091 error = true; //don't bother with the rest of 092 //the page 093 } 094 } 095 %> 096 <% 097 if (error == false && searcher != null) { // if we've had no errors 098 // searcher != null was to handle 099 // a weird compilation bug 100 thispage = maxpage; // default last element to maxpage 101 hits = searcher.search(query); // run the query 102 if (hits.length() == 0) { // if we got no results tell the user 103 %> 104 <p> I'm sorry I couldn't find what you were looking for. </p> 105 <% 106 error = true; // don't bother with the rest of the 107 // page 108 } 109 } 110 111 if (error == false && searcher != null) { 112 %> 113 <table> 114 <tr> 115 <td>Document</td> 116 <td>Summary</td> 117 </tr> 118 <% 119 if ((startindex + maxpage) > hits.length()) { 120 thispage = hits.length() - startindex; // set the max index 121 } //to maxpage or last actual search result whichever is less 122 // for each element 123 for (int i = startindex; i < (thispage + startindex); i++) { 124 %> 125 <tr> 126 <% 127 Document doc = hits.doc(i); //get the next document 128 String doctitle = doc.get("title"); //get its title 129 String url = doc.get("path"); //get its path field 130 if (url != null && url.startsWith("../webapps/")) { // strip 131 url = url.substring(10); //off ../webapps prefix if present 132 } 133 if ((doctitle == null) || doctitle.equals("")) //use the path 134 doctitle = url; // if it has no title 135 //then output! 136 %> 137 <td><a href="<%=url%>"><%=doctitle%></a></td> 138 <td><%=doc.get("summary")%></td> 139 </tr> 140 <% 141 } 142 %> 143 <% if ( (startindex + maxpage) < hits.length()) { //if there are 144 // more results...display the more link 145 146 String moreurl="results.jsp?query=" + 147 URLEncoder.encode(queryString) + //construct the "more" link 148 "&maxresults=" + maxpage + 149 "&startat=" + (startindex + maxpage); 150 %> 151 <tr> 152 <td></td><td><a href="<%=moreurl%>">More Results>> </a></td> 153 </tr> 154 <% 155 } 156 %> </table> 158 159 <% } //then include our footer. 160 if (searcher != null) 161 searcher.close(); 162 %> 163 <%@includefile="footer.jsp"%> |
测试请求
index.jsp提交后的URL请求包含三个基本参数:查询条件(query)、分页设置(maxresults)
和起始记录位置(startat),具体格式如下:
http://localhost:8080/luceneweb/results.jsp?query=hello+world&maxresults=100&startat=0
如果将result.jsp视为一个单元,则URL请求的参数对应的就是result.jsp这个单元的输入参数。通过设计不同的参数数据,达到代码覆盖的目标。这一类型的测试类似于接口测试,属于黑盒性质的测试。
可以通过手工输入URL并比较返回结果进行测试,单元测试应用在这里的优点在于测试的自动化。当然也可以通过QTP、Robot一类的功能自动化测试工具来完成,这些不在本章的讨论范围内。这里给出的例子是JUnit框架下如何应用单元测试技巧完成这一类测试。
版权声明:51Testing软件测试网及相关内容提供者拥有51testing.com内容的全部版权,未经明确的书面许可,任何人或单位不得对本网站内容复制、转载或进行镜像。51testing软件测试网欢迎与业内同行进行有益的合作和交流,如果有任何有关内容方面的合作事宜,请联系我们。