软件工程第二次作业

Github仓库链接:https://github.com/users/Lee-Kuengkai/3123004356

这个作业属于哪个课程 23级计科12班
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13468
这个作业的目标 提高我的项目开发能力,设计并实现一个论文查重系统,通过计算两篇论文的相似度来检测抄袭,继续熟悉Git操作

一、PSP表格(预估时间)

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

计算模块接口的设计与实现过程
代码组织与架构设计
本论文查重系统采用模块化设计理念,将功能分解为多个高内聚、低耦合的独立模块。系统架构基于分层设计原则,包含输入处理层、核心计算层和结果输出层,确保各层职责清晰,便于维护和扩展。
模块划分与职责分配
系统包含以下核心模块,每个模块承担特定职责:

  1. 文本预处理模块
    • 负责原始文本的清洗、标准化和分词处理
    • 实现n-gram特征提取功能
    • 处理特殊字符、标点符号和格式统一
  2. 文件处理模块
    • 负责文件的读写操作
    • 支持多种编码格式自动检测与转换
    • 实现大文件的分块读取机制
  3. 相似度计算模块
    • 实现多种相似度算法(余弦相似度、Jaccard相似度等)
    • 提供算法组合与权重配置功能
    • 优化计算效率,支持大规模文本处理
  4. 结果输出模块
    • 格式化输出查重结果
    • 支持多种输出格式(纯文本、结构化数据等)
    • 生成详细查重报告
  5. 异常处理模块
    • 统一处理各类运行时异常
    • 提供友好的错误提示信息
    • 确保系统稳定性和可靠性

image

独到之处与创新点

  1. 多粒度特征提取:结合字符级和词汇级特征
    • 既考虑局部文本片段相似性
    • 又考虑整体文本结构相似性
  2. 自适应参数调整:根据输入特征动态调整算法参数
    • 无需用户手动配置
    • 适应各种类型和长度的文本
  3. 增量式计算:支持流式文本处理
    • 无需加载全文即可开始处理
    • 大幅降低内存需求

性能分析截图(由于硬件问题,这次采用cmd来展示)
image

计算模块异常处理说明
在论文查重系统中,我们设计了全面的异常处理机制,确保系统在各种异常情况下能够优雅地处理错误,提供清晰的错误信息,并安全退出。以下是系统中各种异常处理的详细说明,包括设计目标和对应的单元测试样例。

  1. 文件不存在异常 (FileNotFoundError)
    设计目标
    • 处理用户提供的文件路径不存在的情况
    • 防止程序尝试读取不存在的文件导致崩溃
    • 提供清晰的错误信息,帮助用户定位问题
    错误场景
    当用户输入的文件路径不存在时触发此异常
    单元测试样例
    import unittest
    import os
    import tempfile
    from main import main
    import sys

class TestFileNotFound(unittest.TestCase):
def test_original_file_not_found(self):
"""测试原文文件不存在的情况"""
# 创建临时抄袭版文件和输出文件
with tempfile.NamedTemporaryFile(delete=False) as plag_file,
tempfile.NamedTemporaryFile(delete=False) as output_file:

        # 设置命令行参数
        sys.argv = ['main.py', 'non_existent_orig.txt', plag_file.name, output_file.name]
        
        # 捕获退出代码
        with self.assertRaises(SystemExit) as cm:
            main()
        
        # 检查退出代码是否为1(错误退出)
        self.assertEqual(cm.exception.code, 1)

def test_plagiarized_file_not_found(self):
    """测试抄袭版文件不存在的情况"""
    # 创建临时原文文件和输出文件
    with tempfile.NamedTemporaryFile(delete=False) as orig_file, \
         tempfile.NamedTemporaryFile(delete=False) as output_file:
        
        # 设置命令行参数
        sys.argv = ['main.py', orig_file.name, 'non_existent_plag.txt', output_file.name]
        
        # 捕获退出代码
        with self.assertRaises(SystemExit) as cm:
            main()
        
        # 检查退出代码是否为1(错误退出)
        self.assertEqual(cm.exception.code, 1)

if name == 'main':
unittest.main()
2. 文件编码异常 (UnicodeDecodeError)
设计目标
• 处理文件编码不兼容的情况
• 支持多种常见编码格式(UTF-8, GBK等)
• 提供明确的错误信息,指导用户解决编码问题
错误场景
当文件使用不支持的编码格式或包含无效字符时触发此异常
单元测试样例
import unittest
import os
import tempfile
from main import main
import sys

class TestEncodingError(unittest.TestCase):
def test_invalid_encoding(self):
"""测试文件编码错误的情况"""
# 创建临时文件
with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as orig_file,
tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as plag_file,
tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as output_file:

        # 使用GBK编码写入文件内容
        with open(orig_file.name, 'wb') as f:
            f.write("测试文本".encode('gbk'))
        
        # 使用UTF-8编码写入文件内容
        with open(plag_file.name, 'w', encoding='utf-8') as f:
            f.write("测试文本")
        
        # 设置命令行参数
        sys.argv = ['main.py', orig_file.name, plag_file.name, output_file.name]
        
        # 捕获退出代码
        with self.assertRaises(SystemExit) as cm:
            main()
        
        # 检查退出代码是否为1(错误退出)
        self.assertEqual(cm.exception.code, 1)

if name == 'main':
unittest.main()
3. 命令行参数异常 (ValueError)
设计目标
• 处理命令行参数数量不足的情况
• 防止程序在缺少必要参数时继续执行
• 提供正确的用法说明,帮助用户正确使用程序
错误场景
当用户没有提供足够的命令行参数时触发此异常
单元测试样例
import unittest
from main import main
import sys

class TestArgumentError(unittest.TestCase):
def test_missing_arguments(self):
"""测试命令行参数不足的情况"""
# 设置不足的命令行参数
test_cases = [
['main.py'], # 无参数
['main.py', 'orig.txt'], # 缺少抄袭版文件和输出文件
['main.py', 'orig.txt', 'plag.txt'] # 缺少输出文件
]

    for args in test_cases:
        with self.subTest(args=args):
            sys.argv = args
            
            # 捕获退出代码
            with self.assertRaises(SystemExit) as cm:
                main()
            
            # 检查退出代码是否为1(错误退出)
            self.assertEqual(cm.exception.code, 1)

if name == 'main':
unittest.main()
4. 输出路径异常 (PermissionError)
设计目标
• 处理无法写入输出文件的情况
• 防止程序在无法写入结果时静默失败
• 提供明确的错误信息,帮助用户解决权限问题
错误场景
当程序没有权限写入输出文件或输出路径无效时触发此异常
单元测试样例
import unittest
import os
import tempfile
from main import main
import sys

class TestOutputError(unittest.TestCase):
def test_output_permission_denied(self):
"""测试输出文件无写入权限的情况"""
# 创建临时原文文件和抄袭版文件
with tempfile.NamedTemporaryFile(delete=False) as orig_file,
tempfile.NamedTemporaryFile(delete=False) as plag_file:

        # 写入测试内容
        with open(orig_file.name, 'w', encoding='utf-8') as f:
            f.write("测试文本")
        with open(plag_file.name, 'w', encoding='utf-8') as f:
            f.write("测试文本")
        
        # 创建无写入权限的输出文件
        with tempfile.NamedTemporaryFile(delete=False) as output_file:
            output_path = output_file.name
            # 在Windows上设置只读属性
            if os.name == 'nt':
                os.chmod(output_path, 0o444)  # 只读权限
            else:  # Unix-like系统
                os.chmod(output_path, 0o444)  # 只读权限
        
        # 设置命令行参数
        sys.argv = ['main.py', orig_file.name, plag_file.name, output_path]
        
        # 捕获退出代码
        with self.assertRaises(SystemExit) as cm:
            main()
        
        # 检查退出代码是否为1(错误退出)
        self.assertEqual(cm.exception.code, 1)

if name == 'main':
unittest.main()
5. 空文件异常 (自定义处理)
设计目标
• 处理输入文件为空的情况
• 防止程序在空文件上执行无效计算
• 提供合理的默认行为(空抄袭版文件相似度为0)
错误场景
当抄袭版文件为空时触发此处理逻辑
单元测试样例
import unittest
import os
import tempfile
from main import main
import sys

class TestEmptyFile(unittest.TestCase):
def test_empty_plagiarized_file(self):
"""测试抄袭版文件为空的情况"""
# 创建临时原文文件、空抄袭版文件和输出文件
with tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as orig_file,
tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as plag_file,
tempfile.NamedTemporaryFile(delete=False, suffix='.txt') as output_file:

        # 写入原文内容
        with open(orig_file.name, 'w', encoding='utf-8') as f:
            f.write("测试文本")
        
        # 创建空抄袭版文件
        open(plag_file.name, 'w', encoding='utf-8').close()
        
        # 设置命令行参数
        sys.argv = ['main.py', orig_file.name, plag_file.name, output_file.name]
        
        # 运行程序
        main()
        
        # 检查输出文件内容
        with open(output_file.name, 'r', encoding='utf-8') as f:
            result = float(f.read().strip())
            self.assertEqual(result, 0.0)

if name == 'main':
unittest.main()

附录:测试样例中查重率展示截图:
image
image
image

posted @ 2025-09-23 20:53  Lee-Kuengkai  阅读(17)  评论(0)    收藏  举报