目录
测试用例
预处理模块测试
测试1:验证预处理后得到的文件整体格式是否是行文本格式
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt
测试步骤:代码如下
@Test
public void isLineTextFormat() throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("D:/raw_data.txt"));
String line;
while ((line = reader.readLine()) != null) {
// 检查每一行是否符合行文本格式
if (!(line.endsWith("\n") || line.endsWith("\r\n") && !line.contains("\r"))) {
System.out.println("并不是每一行都是行文本格式!");
break;
}
}
if ((line = reader.readLine()) == null){
//走到这里说明走完了每一行并且都不是行文本
System.out.println("每一行都是行文本格式");
}
}
期望结果:验证预处理后得到的文件整体格式是行文本格式
实际结果:验证预处理后得到的文件整体格式不是行文本格式
测试2:验证标题是否和html文件名一致
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt Java API文档
测试步骤:代码如下
@Test
public void isHTMLFile() throws IOException {
boolean isContained = false;
//1.枚举出INPUT_PATH 下所有的html文件(递归)
ArrayList<File> fileList = new ArrayList<>();
enumFile("C:\\Program Files\\Java\\jdk1.8.0_192\\docs\\api",fileList);
System.out.println(fileList);
//看行文本格式的每一行中的文件名是否被包含在里面
BufferedReader reader = new BufferedReader(new FileReader("d:/raw_data.txt"));
String line;
while ((line = reader.readLine()) != null) {
isContained = false;
// 跳过空行和注释行
if (line.trim().isEmpty() || line.trim().startsWith("#")) {
continue;
}
// 检查每一行是否包含集合中的其中一个文件名
for (File fileName : fileList) {
if (line.contains(fileName.getName().substring(0,fileName.getName().length() - ".html".length())) ){
//执行到这里说明包含
isContained = true;
break;
}
}
}
//循环执行完成了,isContained == true,说明每一行都包含集合中的其中一个文件名
if (isContained == true){
System.out.println("标题和html文件名一致");
}else {
System.out.println("并不是每一行标题都与html文件名一致");
}
}
期望结果:标题和html文件名一致
实际结果:标题和html文件名一致
测试3:验证每一行中是不是都包含3个字段,是否用\3分割
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt
测试步骤:代码如下
@Test
public void hasThreeFields() throws IOException {
Boolean hasThreeField = false;
BufferedReader reader = new BufferedReader(new FileReader("d:/raw_data.txt"));
String line;
while ((line = reader.readLine()) != null) {
hasThreeField = false;
// 跳过空行和注释行
if (line.trim().isEmpty() || line.trim().startsWith("#")) {
continue;
}
// 使用`\3`作为分隔符,将该行文本拆分成字段数组
String[] fields = line.split("\3");
// 检查字段数组的长度是否等于3
if (fields.length == 3) {
hasThreeField = true;
}
}
//走到这一步如果hasThreeField == true 说明每一行都包括三个字段,并且用\3分割
if (hasThreeField == true){
System.out.println("每一行中都包含3个字段,是用\\3分割");
}else {
System.out.println("每一行中并非都包含3个字段");
}
}
期望结果:每一行中都包含3个字段,且用\3分割
实际结果:每一行中都包含3个字段,且用\3分割
测试4:验证url是否是正确的,是否能跳转到线上文档页面
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt
测试步骤:代码如下
@Test
//验证url是否是正确的,是否能跳转到线上文档页面
public void isValidURL() throws IOException {
Boolean URLisValid = true;
List<String> urlList = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader("d:/raw_data.txt"));
String line;
while ((line = reader.readLine()) != null) {
// 跳过空行和注释行
if (line.trim().isEmpty() || line.trim().startsWith("#")) {
continue;
}
// 使用`\3`作为分隔符,将该行文本拆分成字段数组
String[] fields = line.split("\3");
//将拿到的url放进urlList中
urlList.add(fields[1]);
}
//遍历URL列表
for (String urlStr : urlList) {
if (!isURLValid(urlStr)) {
URLisValid = false;
System.out.println("url无效");
break;
}
}
if (URLisValid == true){
System.out.println("所有URL都有效");
}
}
//创建HttpURLConnection或HttpClient对象,并使用该URL创建连接。
//发送HTTP请求并获取响应状态码。
//根据响应状态码判断URL是否有效。通常情况下,200表示成功,其他状态码可能表示错误或重定向
private boolean isURLValid(String urlStr) {
try {
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
return (responseCode == HttpURLConnection.HTTP_OK);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
期望结果:url是正确的,且能跳转到线上文档页面
实际结果:url是正确的,且能跳转到线上文档页面
测试5:验证正文格式是否正确, html标签是否去掉,是否把\n去掉
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt
测试步骤:代码如下
@Test
public void isTextFormatValid() throws IOException {
Boolean TextFormatValid = true;
BufferedReader reader = new BufferedReader(new FileReader("D:/raw_data.txt"));
String line;
while ((line = reader.readLine()) != null) {
TextFormatValid = true;
// 跳过空行和注释行
if (line.trim().isEmpty() || line.trim().startsWith("#")) {
continue;
}
// 检查该行是否包含HTML标签
if (containsHTMLTags(line)) {
System.out.println("包含html标签");
TextFormatValid = false;
break;
}
// 检查该行是否包含换行符
if (containsNewLine(line)) {
System.out.println("包含换行符号");
TextFormatValid = false;
break;
}
}
//走到这如果还是true说明不包含上面任何一个
if (TextFormatValid == true){
System.out.println("不包含换行符和html符号");
}
}
private boolean containsHTMLTags(String line) {
// 使用正则表达式或其他方式检测是否存在HTML标签
// 以下示例仅为演示目的,可以根据具体情况进行修改
String regex = "<[^>]+>";
return line.matches(".*" + regex + ".*");
}
private static boolean containsNewLine(String line) {
// 检测是否包含换行符
return line.contains("\n") || line.contains("\r\n");
}
期望结果:正文格式是正确,不包含html标签以及\n
实际结果:正文格式是正确,不包含html标签以及\n
索引模块
测试6:.验证通过给定的文档ID,能否正确获取到对应的DocInfo对象
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt
测试步骤:代码如下
@Test
public void indexText() throws IOException {
// 创建一个Index对象
Index index = new Index();
index.build("d:/raw_data.txt");
// 假设已经构建好了正排索引forwardIndex和倒排索引invertedIndex
// 获取指定文档ID的DocInfo对象
int docId = 3; // 假设需要获取的文档ID为0
DocInfo docInfo = index.getDocInfo(docId);
if (docInfo != null) {
System.out.println("search ID: " + docId);
System.out.println("ID: " + docInfo.getDocId());
System.out.println("Title: " + docInfo.getTitle());
System.out.println("URL: " + docInfo.getUrl());
System.out.println("Content: " + docInfo.getContent());
} else {
System.out.println("Document ID " + docId + " does not exist.");
}
}
期望结果:通过给定的文档ID,能正确获取到对应的DocInfo对象
实际结果:通过给定的文档ID,能正确获取到对应的DocInfo对象
测试7:验证当给定一个不存在的文档ID时,是否返回null或者合适的错误标识。
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt 数据:3
测试步骤:代码同上
期望结果:当给定一个不存在的文档ID时,返回null或者合适的错误标识。
实际结果:当给定一个不存在的文档ID时,代码抛出边界值异常
测试8:验证给定一个词,能否正确获取到对应的倒排列表
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt 数据:arraylist
测试步骤:
@Test
public void invertedIndexTest() throws IOException {
// 创建一个Index对象
Index index = new Index();
index.build("d:/raw_data.txt");
// 假设已经构建好了正排索引forwardIndex和倒排索引invertedIndex
// 获取指定词的倒排列表
String term = "arraylist"; // 假设需要获取的词为"arraylist"
ArrayList<Index.Weight> invertedList = index.getInverted(term);
if (invertedList != null && !invertedList.isEmpty()) {
System.out.println("Inverted List for term: " + term);
for (Index.Weight weight : invertedList) {
System.out.println("Doc ID: " + weight.docId);
System.out.println("Weight: " + weight.weight);
System.out.println("----------------------");
}
} else {
System.out.println("No inverted list found for term: " + term);
}
}
期望结果:给定一个词,能正确获取到对应的倒排列表
实际结果:给定一个词,能正确获取到对应的倒排列表
测试9:验证当给定一个不存在的词时,是否返回空的倒排列表或者合适的错误标识。
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt 数据:hahaha
测试步骤:代码同上
期望结果:当给定一个不存在的词时,返回空的倒排列表或者合适的错误标识。
实际结果:当给定一个不存在的词时,返回空的倒排列表
测试10:验证在给定的输入文件路径下,是否能够成功构建正排索引和倒排索引。
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:raw_data.txt
测试步骤:
@Test
public void indexIsSuccess(){
// 创建一个Index对象
Index index = new Index();
String inputPath = "d:/raw_data.txt"; // 替换为实际的输入文件路径
try {
// 构建索引
index.build(inputPath);
// 验证构建后的正排索引和倒排索引是否符合预期
System.out.println("Index build successfully!");
} catch (Exception e) {
System.out.println("Failed to build index: " + e.getMessage());
}
}
期望结果:在给定的输入文件路径下,能够成功构建正排索引和倒排索引。
实际结果:在给定的输入文件路径下,能够成功构建正排索引和倒排索引。
搜索模块
测试11:针对搜索结果,里面包含的标题是否正确
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:arraylist
测试步骤:
@Test
public void isContainArrayList() throws IOException {
Searcher searcher = new Searcher();
List<Result> results = searcher.search("ArrayList");
for (Result result : results) {
System.out.println(result);
System.out.println("============================");
}
}
期望结果:针对搜索结果,里面包含的标题都正确
实际结果:针对搜索结果,里面包含的标题都正确
测试12:针对搜索结果,是否按照权重排序
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:arraylist
测试步骤:
@Test
public void isWeightSort() throws IOException {
// 创建 Searcher 对象
Searcher searcher = new Searcher();
// 输入查询词
String query = "arraylist";
// 执行搜索
List<Result> results = searcher.search(query);
// 遍历搜索结果,并打印权重
int prevWeight = Integer.MAX_VALUE; // 用于记录前一个结果的权重,初始化为一个较大的值
boolean sorted = true; // 标记搜索结果是否按照权重排序
for (Result result : results) {
int weight = result.getWeight(); // Result 类中有一个获取权重的方法 getWeight()
System.out.println("Weight: " + weight);
if (weight > prevWeight) {
sorted = false;
break;
}
prevWeight = weight;
}
// 输出搜索结果是否按照权重排序
if (sorted) {
System.out.println("Search results are sorted by weight.");
} else {
System.out.println("Search results are not sorted by weight.");
}
}
期望结果:针对搜索结果,是按照权重排序
实际结果:针对搜索结果,是按照权重排序
测试13:针对搜索结果,URL是否能跳转
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:arraylist
测试步骤:
@Test
public void isUrlValid() throws IOException {
// 创建 Searcher 对象
Searcher searcher = new Searcher();
// 输入查询词
String query = "arraylist";
// 执行搜索
List<Result> results = searcher.search(query);
for (Result result : results) {
String clickUrl = result.getClickUrl(); // Result 类中有获取点击URL的方法 getClickUrl()
boolean isAccessible = checkUrlAccessibility(clickUrl);
if (isAccessible) {
System.out.println("URL is accessible: " + clickUrl);
} else {
System.out.println("URL is not accessible: " + clickUrl);
break;
}
}
}
private static boolean checkUrlAccessibility(String urlStr) {
try {
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("HEAD");
int responseCode = connection.getResponseCode();
// 判断响应状态码是否为2xx,表示请求成功
return responseCode >= 200 && responseCode < 300;
} catch (IOException e) {
// 发生异常则表示无法访问该URL
return false;
}
期望结果:针对搜索结果,URL都能跳转
实际结果:针对搜索结果,URL都能跳转
测试14:针对搜索结果,描述是否包含指定的词.
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:arraylist
测试步骤:
@Test
public void isContentValid() throws IOException {
// 创建 Searcher 对象
Searcher searcher = new Searcher();
// 输入查询词
String query = "ArrayList";
List<Term> terms = ToAnalysis.parse(query).getTerms();
// 执行搜索
List<Result> results = searcher.search(query);
for (Result result : results) {
String content = result.getDesc(); // 假设Result类中有获取内容的方法 getContent()
for (Term term : terms){
String AnsjDesc = term.getName();
if (content.contains(query)) {
System.out.println("Content contains the specified word " );
break;
} else {
System.out.println("Content does not contain the specified word " );
}
}
}
}
期望结果:针对搜索结果,描述中包含指定的词.
实际结果:针对搜索结果,描述中包含指定词语或者其分词
测试15:针对搜索结果,搜索结果的数目是否符合预期(预期要20条以上)
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:arraylist
测试步骤:
@Test
public void SearchCount() throws IOException {
// 创建 Searcher 对象
Searcher searcher = new Searcher();
int searchCount = 0;
// 输入查询词a
String query = "ArrayList";
// 执行搜索
List<Result> results = searcher.search(query);
//搜索出来的条目要大于20
for (Result result : results){
searchCount++;
}
System.out.println(searchCount);
}
期望结果:针对搜索结果,搜索结果的数目符合预期(20条以上)
实际结果:针对搜索结果,搜索结果的数目符合预期(20条以上)
测试14:搜索时间是否符合预期
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3
测试数据:arraylist
测试步骤:
@Test
public void SearcherTime() throws IOException {
long timeBegin = System.currentTimeMillis();
// 创建 Searcher 对象
Searcher searcher = new Searcher();
int searchCount = 0;
// 输入查询词a
String query = "ArrayList";
// 执行搜索
List<Result> results = searcher.search(query);
long timeEnd = System.currentTimeMillis();
System.out.println("search time : " + (timeEnd - timeBegin));
}
期望结果:预期2秒以内
实际结果:花费了10秒以上,不符合预期
前端模块
测试15:界面是否符合要求
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3,Google Chrome版本116.0.5845
测试数据:无
预期界面:
实际界面:符合要求
测试15:输入以后点击搜索是否有反应
测试环境:win10,IntelliJ IDEA Community Edition 2022.3.3,Google Chrome版本116.0.5845
测试数据:arraylist
测试步骤:
@Test
public void isValid(){
driver.get("http://127.0.0.1:8080/java_doc_searcher/index.html");
driver.findElement(By.cssSelector("#app > div:nth-child(2) > div.col-md-5 > input")).sendKeys("arraylist");
driver.findElement(By.cssSelector("#app > div:nth-child(2) > div.col-md-1 > button")).click();
//2.获取页面上所有页面标题对应的元素,注意使用的是findElements,后面有个s
int title_num = driver.findElements(By.cssSelector("#app > div:nth-child(3) > div.title > a")).size();
//如果元素数量不为0,那么测试通过
Assertions.assertNotEquals(0,title_num);
}
期望结果:条数不为0
实际结果:用例通过,条数不为0
总结:搜索方面的性能有待提升,尤其是构建倒排索引花费的时间太长了