单元测试
构建索引模块
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按照权重值排序后的列表页
测试结果
搜索多个关键字中间加入逗号
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入多个关键字加逗号
3.点击搜索
测试数据
搜索:java,string
期望结果
搜索成功,打开包含java string按照权重值排序后的列表页
测试结果
搜索多个关键词间隔多个空格
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入多个关键字加空格
3.点击搜索
测试数据
搜索:java string list
期望结果
搜索成功,打开包含java string list按照权重值排序后的列表页
测试结果
搜索英文和数字的混合
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL:http://localhost:8080/index.html
2.点击搜索框,输入英文和数字的混合数字
3.点击搜索
测试数据
搜索list3
期望结果
搜索成功,打开包含list3的列表页
测试结果
搜索数字
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入一个数字
3.点击搜索
测试数据
搜索3
期望结果
搜索成功,打开包含3的列表页
测试结果
测试2 点击标题可以正常跳转
模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL:http://localhost:8080/index.html
2.点击搜索框,输入关键字
3.点击搜索后跳转
4.点击结果中的标题
测试数据
搜索数据:map
url:https://docs.oracle.com/javase/8/docs/api/java/util/class-use/Map.html
期望结果
点击url后正确跳转到对应的网页
测试结果
正确显示页面
测试3 翻页功能
点击翻页按钮,正常翻页
模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URLhttp://localhost:8080/index.html
2.点击搜索框,输入关键字
3.点击搜索后跳转
4.点击上一页,上一页正确显示内容
测试数据
搜索:java
期望结果
点击上一页,下一页都能正常显示内容
测试结果
点击上一页:
点击下一页:
搜索最后一页的下一页
模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
在网页栏中输入url地址,观察结果
测试数据
搜索数据:php
url:http://localhost:8080/web?query=php&page=2
期望结果
弹出错误界面
测试结果
搜索第一页的上一页
模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
在网页栏中输入url地址,观察结果
测试数据
搜索数据:php
url:http://localhost:8080/web?query=php&page=0
期望结果
停留在原页面即可
测试结果
测试4 高亮显示
模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入map
3.点击搜索
测试数据
搜索:map
期望结果
搜索成功,所有关于map的单词都高亮显示
测试结果
测试5:历史记录展示
模块
主页展示模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1:在主页展示模块的搜索框中输入一个字母
2:看是否显示之前搜索的内容
测试数据
输入:a
期望结果
会出现之前以a开头的所有搜索记录
测试结果
易用性测试
搜索大写字母,自动转小写
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL:http://localhost:8080/index.html
2.点击搜索框,输入ARRAY
3.点击搜索
测试数据
搜索:ARRAY
期望结果
搜索到的内容都跟小写有关
测试结果
内容复制粘贴
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL:http://localhost:8080/index.html
2.点击搜索框,输入array,并复制
3.删除掉后再点击粘贴
测试数据
输入:array
期望结果
成功复制粘贴
测试结果
输入后,复制后删掉,成功粘贴:
回车键搜索
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL:http://localhost:8080/index.html
2.点击搜索框,输入array
3.点击搜索
测试数据
输入:array
期望结果
点击回车键后正确弹出搜索结果
测试结果
下拉框时,搜索框不变
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.打开浏览器,输入URL
2.点击搜索框,输入array
3.点击搜索
测试数据
输入array
期望结果
下拉查看搜索结果时,搜索框不变
测试结果
兼容性测试
模块
搜索模块,主页展示模块
测试环境
这里因为项目并没有推到线上使用,所以就选择当下市场上主流的浏览器覆盖,后期推到线上后,在添加其他浏览器测试即可
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
Firefox 103.0.2 (20220808125904) PC端 Windows系统
Microsoft Edge版本 104.0.1293.54 (正式版本) (64 位) PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1:在Chorme浏览器中输入url:http://localhost:8080/index.html,然后在搜索框中输入关键字,正确弹出页面.
2: 在Firefox 浏览器中输入url:http://localhost:8080/index.html,然后在搜索框中输入关键字,正确弹出页面.
3:在Microsoft Edge浏览器中输入url:http://localhost:8080/index.html,然后在搜索框中输入关键字,正确弹出页面.
测试数据
url : http://localhost:8080/index.html
关键字 :java
期望结果
在各个浏览器中输入url后,输入关键字,正确弹出内容页面
测试结果
Chorme浏览器:
Firefox 浏览器:
Microsoft Edge浏览器:
性能测试
正排索引构建时间
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
后台运行构建正排索引代码,查看运行时间
期望结果
构建正排索引时间小于1s
测试结果
正排索引构建时间为0.931s,低于1s
倒排索引构建时间
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
后台运行构建倒排索引代码,查看运行时间
期望结果
构建倒排索引时间小于1min
测试结果
倒排索引构建时间为13s,远远小于1min
搜索时间
搜索单个关键字
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.点击搜索框输入数据
2.打开chorme浏览器进行调试,摁fn+F12查看接口的响应时间
测试数据
搜索:java
期望结果
搜索时间小于1s
测试结果
接口响应时间小于1s,符合预期
搜索多个关键字带空格
模块
搜索模块
测试环境
Chrome 版本 103.0.5060.66(正式版本) (64 位)PC端 Windows系统
前置条件
在IDEA中运行web项目
测试步骤
1.点击搜索框输入数据
2.打开chorme浏览器进行调试,摁fn+F12查看接口的响应时间
测试数据
搜索:java string
期望结果
搜索时间小于1s
测试结果
接口响应时间小于1s,符合预期