软件工程导论作业2:论文查重

github地址

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13229
这个作业的目标 通过开发个人项目,实现项目单元测试

一、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 20
Estimate 估计这个任务需要多少时间 900 1000
Development 开发 420 600
Analysis 需求分析 (包括学习新技术) 30 25
Design Spec 生成设计文档 20 20
Design Review 设计复审 20 30
Coding Standard 代码规范 (为目前的开发制定合适的规范) 20 35
Design 具体设计 50 40
Coding 具体编码 50 70
Code Review 代码复审 20 20
Test 测试(自我测试,修改代码,提交修改) 40 60
Reporting 报告 20 30
Test Repor 测试报告 40 60
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 20
合计 780 1020

二、模块接口的设计与实现过程

模块接口设计

类和函数设计

  1. DulcateCheckerMain 类:作为主类,负责处理命令行参数,调用文件读取、文本处理和结果输出。
    主要方法main,处理命令行参数,调用其他类的方法来执行具体任务。
  2. FileProcess 类:负责文件的读取和写入。
    方法readFile 读取文件内容,writeResult 将处理结果写入文件。
  3. TextProcess 类:负责文本处理,包括分词和计算Jaccard相似度。
    方法tokenize 对文本进行分词,calculateJaccardSimilarity 计算两个词集的Jaccard相似度。

实现过程

关系

类名 方法名 职责描述
DulcateCheckerMain main 程序入口,处理命令行参数,调用其他类方法执行任务。
FileProcess readFile 读取文件内容并返回字符串。
writeResult 将相似度结果写入指定文件。
TextProcess tokenize 对文本进行分词,返回词集合。
calculateJaccardSimilarity 计算两个词集合的Jaccard相似度。

流程图

graph TD A[开始] --> B{检查命令行参数} B -->|参数正确| C[读取原始文件] B -->|参数错误| D[输出使用说明] D --> E[结束] C --> F[读取疑似抄袭文件] F --> G[分词处理] G --> H[计算Jaccard相似度] H --> I[写入结果到文件] I --> J[异常处理] J --> E

算法的关键

  1. 分词算法:使用ToAnalysis.parse 方法对文本进行分词,这是文本处理的基础。
  2. Jaccard相似度计算:计算两个词集的交集和并集,然后计算相似度。这是核心算法,用于评估文本的相似度。

三、性能分析

使用性能分析工具(如 Visual Studio 2017 的性能分析器或 JProfiler)来识别程序中的性能瓶颈

已删除黄色提示



四、单元测试

测试说明

  1. DulcateCheckerMainTest主程序测试
    testMain: 这个测试方法验证了 DulcateCheckerMain 类的 main 方法能否正确处理文件读取、文本比较,并正确写入结果。测试数据包括两个临时文件,一个作为原始文本,另一个作为疑似抄袭文本。
    testExceptionHandling: 这个测试方法检查当输入参数不正确时(例如,其中一个参数为 null),程序是否能抛出异常。
  2. FileProcessTest文件处理测试
    testReadFile: 验证 readFile 方法能否正确读取文件内容。测试中创建了一个临时文件,并写入了测试数据,然后通过 readFile 方法读取并验证内容。
    testWriteResult: 验证 writeResult 方法能否将结果正确写入到文件中。测试中创建了一个临时文件,并通过 writeResult 方法写入了一个测试结果,然后读取并验证文件内容。
  3. TextProcessTest文本处理测试
    testTokenize: 这个测试方法验证 tokenize 方法能否正确分词。测试中使用了一段包含多种字符的文本,验证分词结果是否包含了所有预期的词汇。
    testCalculateJaccardSimilarity: 验证 calculateJaccardSimilarity 方法能否正确计算两个词集的Jaccard相似度。测试中创建了两个词集,并验证计算结果是否符合预期。

构造测试数据的思路

  1. 简单性:测试数据应尽可能简单,以减少测试的复杂性,同时覆盖所有重要的场景。
  2. 全面性:测试数据应覆盖所有可能的输入情况,包括正常情况和边界情况。
  3. 可重复性:测试数据应能在任何时候重复使用,以确保测试结果的一致性。
  4. 独立性:每个测试应独立于其他测试,以确保一个测试的失败不会影响到其他测试。

测试函数

主函数部分单元测试

public class DulcateCheckerMainTest {
//读取文件、方法测试
    @Test
    public void testMain() throws Exception {
        File origFile = File.createTempFile("orig", ".txt");
        File plagFile = File.createTempFile("plag", ".txt");
        File resultFile = File.createTempFile("result", ".txt");

        try (PrintWriter writer = new PrintWriter(new FileWriter(origFile))) {
            writer.println("This is the original text.");
        }
        try (PrintWriter writer = new PrintWriter(new FileWriter(plagFile))) {
            writer.println("This is the plagiarized text.");
        }

        String[] args = {origFile.getAbsolutePath(), plagFile.getAbsolutePath(), resultFile.getAbsolutePath()};
        DulcateCheckerMain.main(args);

        try (BufferedReader reader = new BufferedReader(new FileReader(resultFile))) {
            String line = reader.readLine();
            assertNotNull(line);
            assertTrue(line.matches("\\d+\\.\\d+"));
        }

        origFile.deleteOnExit();
        plagFile.deleteOnExit();
        resultFile.deleteOnExit();
    }
//异常处理测试
    @Test
    public void testExceptionHandling() throws IOException {
        File plagFile = File.createTempFile("plag", ".txt");
        File resultFile = File.createTempFile("result", ".txt");
        try (PrintWriter writer = new PrintWriter(new FileWriter(plagFile))) {
            writer.println("This is the plagiarized text.");
        }

        String[] args = {null, plagFile.getAbsolutePath(), resultFile.getAbsolutePath()};

        assertThrows(Exception.class, () -> {
            DulcateCheckerMain.main(args);
        });
    }
}

文件处理单元测试

public class FileProcessTest {
//读文件
    @Test
    public void testReadFile() throws IOException {
        File tempFile = File.createTempFile("testRead", ".txt");
        try (PrintWriter writer = new PrintWriter(new FileWriter(tempFile))) {
            writer.println("This is a test file.");
        }

        String content = FileProcess.readFile(tempFile.getAbsolutePath());
        assertEquals("This is a test file.\n", content);

        tempFile.deleteOnExit();
    }
//写文件
    @Test
    public void testWriteResult() throws IOException {
        File resultFile = File.createTempFile("testResult", ".txt");
        FileProcess.writeResult(resultFile.getAbsolutePath(), 0.85);
        try (BufferedReader reader = new BufferedReader(new FileReader(resultFile))) {
            String line = reader.readLine();
            assertNotNull(line);
            assertEquals("0.85", line);
        }
        resultFile.deleteOnExit();
    }

文本处理单元测试

public class TextProcessTest {
//分词测试
    @Test
    public void testTokenize() {
        String text = "你好,我是哈哈。";
        Set<String> tokens = TextProcess.tokenize(text);

        assertTrue(tokens.contains("你好"));
        assertTrue(tokens.contains(","));
        assertTrue(tokens.contains("我"));
        assertTrue(tokens.contains("是"));
        assertTrue(tokens.contains("哈哈"));
        assertTrue(tokens.contains("。"));
    }
//相似度计算测试
    @Test
    public void testCalculateJaccardSimilarity() {
        Set<String> set1 = new HashSet<>();
        set1.add("a");
        set1.add("b");
        set1.add("c");

        Set<String> set2 = new HashSet<>();
        set2.add("b");
        set2.add("c");
        set2.add("d");
        double similarity = TextProcess.calculateJaccardSimilarity(set1, set2);
        assertEquals(0.5, similarity, 0.01);
    }
}

五、异常处理

文件不存在异常(FileNotFoundException)
设计目标:在文件路径指向不存在的文件时,应通知用户文件无法找到,避免程序进一步执行错误的操作。
单元测试样例:

//异常处理测试
    @Test
    public void testExceptionHandling() throws IOException {
        File plagFile = File.createTempFile("plag", ".txt");
        File resultFile = File.createTempFile("result", ".txt");
        try (PrintWriter writer = new PrintWriter(new FileWriter(plagFile))) {
            writer.println("This is the plagiarized text.");
        }

        String[] args = {null, plagFile.getAbsolutePath(), resultFile.getAbsolutePath()};

        assertThrows(Exception.class, () -> {
            DulcateCheckerMain.main(args);
        });
    }
}

错误场景:文件路径错误或文件已被删除,但程序仍尝试读取它。

测试结果




posted @ 2024-09-10 10:11  菜菜X  阅读(110)  评论(0编辑  收藏  举报