第一次个人编程作业

| 这个作业属于哪个课程 | 软件工程 |
| ---- | :----: | :----: |
| 这个作业要求在哪里 | 作业要求 |
| 这个作业的目标 | 论文查重算法设计+单元测试+JProfiler+PSP表格+Git |

代码链接

Github链接

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

整体流程

1.PaperCheckMain.main方法接收三个参数,分别为 [原文文件] [抄袭版论文的文件] [答案文件]
2.将两个文件的文本内容分别转换为字符串
3.CosSimilarityServiceImpl.getSimilarity,使用余弦相似算法对比字符串
4.将结果输出到指定文件

工程结构

项目主要类

  • PaperCheckMain:程序的入口
  • CosSimilarityServiceImpl:余弦算法的实现计算相似度
  • FileUtil:处理文件、将文件内容转化为字符串、将结果输出到指定文件中
  • IKSegmenter: 分词器

命令行运行效果

算法描述

文本相似度算法:余弦相似度算法

  • 1.分词
  • 2.列出所有词
  • 3.计算词频向量
  • 4.利用HashMap存储词和对应的词频,词为健,词频为值
  • 5.使用余弦公式计算cos值
  • 6.cos值越接近1,两篇文章相似度越高
  • 7.参考文章
  • 8.余弦公式

计算模块接口部分的性能改进

使用JProfiler进行单元测试对性能进行监控

  • 类的内存消耗

  • CPU Load

  • 堆内存情况

  • 改进思路
    1.最耗时的地方是对字符串进行分词操作,但对IK分词器难以优化,所以无法对分词进行操作,或许可能更换更加优秀的分词器
    2.可对字符串的判断进行优化,比如利用String.equals进行对比或判断字符串文本内容是否为空简略优化

计算模块的单元测试展示

单元测试使用Junit

  • 测试路径为null的情况、测试空文本、相同文本、不同文本、干扰文本、参数输入错误等情况
  • PaperCheckMain.process使用静态方法,输入参数为 [原文文件] [抄袭版论文的文件] [答案文件]

    /**
     * 测试原创论文路径为null的情况
     */
    @Test
    public void testForOriginalContextNull(){
        try {
            PaperCheckMain.process(null,"E:\\test\\orig_0.8_add.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }

    /**
     * 测试抄袭论文路径为null的情况
     */
    @Test
    public void testForCopyContextNull(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt",null,"E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }

    /**
     * 测试输出结果文件路径为null的情况
     */
    @Test
    public void testForResultFileAddressNull(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_add.txt",null);
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }

    /**
     * 测试输出抄袭论文为空文本的情况
     */
    @Test
    public void testForCopyContextEmptyNull(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\empty.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试对比orig.txt与orig_0.8_add.txt
     */
    @Test
    public void testForCopyContextAdd(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_add.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试对比orig.txt与orig_0.8_del.txt
     */
    @Test
    public void testForCopyContextDel(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_del.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试对比orig.txt与orig_0.8_dis_1.txt
     */
    @Test
    public void testForCopyContextDis1(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_dis_1.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试对比orig.txt与orig_0.8_dis_10.txt
     */
    @Test
    public void testForCopyContextDis10(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_dis_10.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试对比orig.txt与orig_0.8_dis_15.txt
     */
    @Test
    public void testForCopyContextDis15(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig_0.8_dis_15.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试相同文档对比
     */
    @Test
    public void testForSameContext(){
        try {
            PaperCheckMain.process("E:\\test\\orig.txt","E:\\test\\orig.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            e.printStackTrace();
        }
    }}

说明测试的方法,构造测试数据的思路

  -单元测试:针对各种不同数据的输入,以及路径参数的输入进行测试

测试结果

测试覆盖率

计算模块部分异常处理说明

针对IOException等文件写入和读取异常,需要进行处理

自定义异常

设计目的

  • 出现IOException时,截取它,抛出自定义异常传递出现的异常信息
  • 命令行参数出现错误时,截取,抛出自定义异常传递出现的异常信息
    /**
     * 测试原创论文路径为null的情况
     */
    @Test
    public void testForOriginalContextNull(){
        try {
            PaperCheckMain.process(null,"E:\\test\\orig_0.8_add.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("输入参数不能为空!");
        }
    }

    /**
     * 测试命令行参数输入错误
     */
    @Test
    public void testForErrorArgs(){
        try {
            PaperCheckMain.process("errorPath","E:\\test\\orig.txt","E:\\test\\result.txt");
        } catch (MyException e) {
            System.out.println("命令行参数错误!");      
            e.printStackTrace();
        }
    }



PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 40
· Estimate · 估计这个任务需要多少时间 40 40
Development 开发 300 320
· Analysis · 需求分析 (包括学习新技术) 30 40
· Design Spec · 生成设计文档 60 80
· Design Review · 设计复审 20 30
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 40 30
· Design · 具体设计 30 30
· Coding · 具体编码 200 220
· Code Review · 代码复审 30 20
· Test · 测试(自我测试,修改代码,提交修改) 30 30
·Reporting 报告 60 60
· Test Repor · 测试报告 30 30
· 合计 850 970
posted @ 2020-09-25 01:04  DDDDARK  阅读(147)  评论(0)    收藏  举报