目录
单元测试
构建索引模块
文档信息对象Document的构建的单元测试
针对每一篇文档进行分析、处理、分词
针对文档内容提取关键字的测试(正则表达式)
测试去掉script
测试去掉标签
完整测试Document类中的parseContent方法
关于ansj分词器的测试
关于构建倒排索引的测试
批量插入的测试
界面测试
测试1 界面布局是否合理,展示位置是否正确
功能测试
测试1 不同搜索方式下的关键字搜索
搜索为空或者为一个空格
搜索一个关键字
搜索多个关键字中间加入空格
搜索多个关键字中间加入逗号
搜索多个关键词间隔多个空格
搜索英文和数字的混合
搜索数字
测试2 点击标题可以正常跳转
测试3 翻页功能
点击翻页按钮,正常翻页
搜索最后一页的下一页
搜索第一页的上一页
测试4 高亮显示
测试5:历史记录展示
易用性测试
搜索大写字母,自动转小写
内容复制粘贴
回车键搜索
下拉框时,搜索框不变
兼容性测试
安全性测试
搜索的数据网络传输中是否被损坏
性能测试
正排索引构建时间
倒排索引构建时间
搜索时间
搜索单个关键字
搜索多个关键字带空格
单元测试
构建索引模块
1.扫描文档目录下的所有文档
以 rootPath 作为根目录,开始进行文件的扫描,把所有符合条件的 File 对象,作为结果,以 List 形式返回
首先在该类上按 Ctrl + Shift + t,可以自己生成测试的类
1.测试时,先给一个根目录的文件,需要确保这个目录存在 && 一定是一个目录,他的文件以 .json 为结尾。当一个文件满足这些条件时,说明是 true 。
2.再得到他的标准文件名
3.使用断言进行判断 Assert,我通过代码得到的文件名如果和我写的正确的文件名相同的话,证明这个测试用例是通过的。
package com.peixinchen.searcher.indexer; import com.peixinchen.searcher.indexer.util.FileScanner; import lombok.SneakyThrows; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.util.Assert; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @SpringBootTest public class Indexer { @Autowired private FileScanner fileScanner; @SneakyThrows @Test void testFileScanner() { // 双\\表示转义 List<File> list = fileScanner.scanFile("D:\\index", file -> { return file.isFile() && file.getName().endsWith(".json"); // return file.isFile() && file.getName().startsWith("forward"); }); // 1. 针对每个 File 对象,调用 file.getCanonicalPath(),得到 String 类型的绝对路径 // 2. 针对结果做排序 // 3. Stream<String> -> List<String> List<String> filenameList = list.stream() .map(file -> { try { return file.getCanonicalPath(); } catch (IOException e) { throw new RuntimeException(e); } }) .sorted() .collect(Collectors.toList()); Assert.isTrue(filenameList.equals(Arrays.asList( "D:\\index\\forward.json" ))); } }
文档信息对象Document的构建的单元测试
针对每一篇文档进行分析、处理、分词
根据扫描出的 html 文件提取他的 标题 和 url 是否正确
package com.peixinchen.searcher.indexer; import com.peixinchen.searcher.indexer.model.Document; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.util.Assert; import java.io.File; import static sun.plugin.javascript.navig.JSType.Document; /** * @author SongBiao * @Date 14:29 */ @SpringBootTest public class DocumentTest { @Test public void testDocumentConstructor() { File rootFile = new File("D:\\学习资料\\搜索引擎\\docs\\api"); File file = new File("D:\\学习资料\\搜索引擎\\docs\\api\\javax\\sql\\DataSource.html"); String urlPrefix = "https://docs.oracle.com/javase/8/docs/api/"; Document document = new Document(file, urlPrefix, rootFile); Assert.isTrue(document.getTitle().equals("DataSource")); Assert.isTrue(document.getUrl().equals("https://docs.oracle.com/javase/8/docs/api/javax/sql/DataSource.html")); } }
针对文档内容提取关键字的测试(正则表达式)
测试去掉script
@Test public void testTrimScriptTag() { String s = "Hello <script>...</script> World"; // 第一步,从 "Hello <script src="...">...</script> World" -> "Hello World",此时注意hello和world之间有三个空格 // 第二部,从 "Hello World" -> "Hello World",把三个空格变成一个 s = s.replaceAll("<script.*?>(.*?)</script>", " ").replaceAll("\\s+", " "); // 这里就是正则替换 String m = "Hello World"; Assert.isTrue(s.equals(m)); }
测试去掉标签
@Test public void testTrimTag() { String s = "<div><h1>你好</h1><p>Hello</p><p>World</p></div>"; s = s.replaceAll("<[^>]*>", " ").replaceAll("\\s+", " ").trim(); String m = "你好 Hello World"; Assert.isTrue(s.equals(m)); }
完整测试Document类中的parseContent方法
我们选取一个文档内容如下:(注意因为java的这些文档都是英文的,所以我们选择的是ISO-8859-1这个字符集,所以我们测试文档中是不会出现中文的):
@Test public void testDocumentContent() { File file = new File("D:\\学习资料\\搜索引擎\\test.html"); String s = "Hello World Holo Wald \"Holo Wald\" is our first application."; Document document = new Document(file, "/", new File("D:\\学习资料\\搜索引擎\\")); //返回的是true即可 Assert.isTrue(s.equals(document.getContent())); }
关于ansj分词器的测试
@Test public void testAnsj() { Result result = ToAnalysis.parse("我爱北京天安门,天安门上太阳升。"); List<Term> termList = result.getTerms(); for (Term term : termList) { System.out.print(term.getName() + ", "); System.out.print(term.getNatureStr() + ", "); System.out.println(term.getRealName()); } }
关于构建倒排索引的测试
编写测试方法:
/* 正排索引的测试方法 */ public void printForwardIndex() { int size = forwardIndex.size(); for (int i = 0; i < size; i++) { int docId = i; IndexDocument indexDocument = forwardIndex.get(docId); System.out.printf("docId: %d -> IndexDocument: %s\n", docId, indexDocument); } } /* 倒排索引的测试方法 */ public void printInvertedIndex() { Set<String> wordSet = invertedIndex.keySet(); for (String word : wordSet) { System.out.printf("%s: \n", word); List<DocWeight> docWeightList = invertedIndex.get(word); for (DocWeight docWeight : docWeightList) { System.out.printf(" docWeight: %s\n", docWeight); } } }
来到我们写的测试类中:
@Test public void testBuildIndex1() { String content = "I want you to know\n" + "\n" + "one thing.\n" + "\n" + "\n" + "\n" + "You know how this is:\n" + "\n" + "if I look\n" + "\n" + "at the crystal moon, at the red branch\n" + "\n" + "of the slow autumn at my window,\n" + "\n" + "if I touch\n" + "\n" + "near the fire\n" + "\n" + "the impalpable ash\n" + "\n" + "or the wrinkled body of the log,\n" + "\n" + "everything carries me to you,\n" + "\n" + "as if everything that exists,\n" + "\n" + "aromas, light, metals,\n" + "\n" + "were little boats\n" + "\n" + "that sail\n" + "\n" + "toward those isles of yours that wait for me.\n"; Document document = new Document("If You Forget Me", "构建索引不需要url", content.replaceAll("\n", " ").replaceAll("\\s+", " ")); System.out.println(document); indexManager.add(document); System.out.println(); System.out.println(); indexManager.printForwardIndex(); System.out.println(); System.out.println(); indexManager.printInvertedIndex(); } @Test public void testBuildIndex2() { Document d1 = new Document("行宫", "url", "寥落古行宫,宫花寂寞红。白头宫女在,闲坐说玄宗。"); Document d2 = new Document("登鹳雀楼", "url", "白日依山尽,黄河入海流。欲穷千里目,更上一层楼。"); Document d3 = new Document("新嫁娘词", "url", "三日入厨下,洗手作羹汤。未谙姑食性,先遣小姑尝。"); Document d4 = new Document("静夜思", "url", "床前明月光,疑是地上霜。举头望明月,低头思故乡。"); Document d5 = new Document("无题", "url", "宫花宫女在,白日月光行。更上一层楼,未谙姑食性。"); indexManager.add(d1); System.out.println(); System.out.println(); indexManager.printForwardIndex(); System.out.println(); System.out.println(); indexManager.printInvertedIndex(); indexManager.add(d2); System.out.println(); System.out.println(); indexManager.printForwardIndex(); System.out.println(); System.out.println(); indexManager.printInvertedIndex(); indexManager.add(d3); System.out.println(); System.out.println(); indexManager.printForwardIndex(); System.out.println(); System.out.println(); indexManager.printInvertedIndex(); indexManager.add(d4); System.out.println(); System.out.println(); indexManager.printForwardIndex(); System.out.println(); System.out.println(); indexManager.printInvertedIndex(); indexManager.add(d5); System.out.println(); System.out.println(); indexManager.printForwardIndex(); System.out.println(); System.out.println(); indexManager.printInvertedIndex(); } }
批量插入的测试
package com.peixinchen.searcher.indexer; import com.peixinchen.searcher.indexer.command.Indexer; import com.peixinchen.searcher.indexer.mapper.IndexDatabaseMapper; import com.peixinchen.searcher.indexer.model.Document; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import java.util.ArrayList; import java.util.List; @SpringBootTest class IndexerApplicationTests { @MockBean // 通过这个 @MockBean 修饰,使得测试的时候,不需要真正的去执行 Indexer bean 下的操作 private Indexer indexer; @Autowired private IndexDatabaseMapper mapper; @Test void batchInsert() { List<Document> list = new ArrayList<>(); for (int i = 0; i < 10; i++) { String s = String.valueOf(i); Document document = new Document(s, s, s); list.add(document); } mapper.batchInsertForwardIndexes(list); for (Document document : list) { System.out.println(document); } } }
对应的批量插入的sql语句如下所示:
insert into forward indexes (itle, url, content) values (?,?, ?),(?,?,?), (?,?, ?), (?,?, ?), (?,?, ?), (?,?, ?), (?,?, ?), (?,?, ?), (?,?, ?), (?,?, ?)
o(String), 0(String), 0(String), 1(String),1(String), 1(String), 2(String), 2(String), 2(String), 3(String),3(String), 3(String), 4(String), 4(String), 4(String), 5(String), 5(String), 5(Strinq), 6(String), 6(String), 6(String), 7(String), 7(String), 7(String), 8(String), 8(String), 8(String), 9(String). 9(String), 9(String)
界面测试
测试1 界面布局是否合理,展示位置是否正确
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
打开浏览器,输入URL
测试数据
URL:http://127.0.0.1:8080/index.html
期望结果
测试结果
界面布局、扫面内容展示位置正确:模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
在搜索框输入搜索内容后,进入搜索界面
测试数据
搜索:php
期望结果测试结果
界面布局、扫面内容展示位置正确:
功能测试
测试1 不同搜索方式下的关键字搜索
搜索为空或者为一个空格
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,不输入内容或者输入一个空格
3.点击搜索
测试数据
空字符或者空格
期望结果
搜索失败,停留在搜索主界面
测试结果
搜索一个关键字
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入一个关键字
3.点击搜索
测试数据
输入Java
期望结果
搜索成功,打开包含java按照权重值排序后的列表页
测试结果
搜索多个关键字中间加入空格
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入多个关键字加空格
3.点击搜索
测试数据
搜索:list string
期望结果
搜索成功,打开包含list string按照权重值排序后的列表页
测试结果