第一次個人作業

LHH778發表於2024-09-12
這個作業屬於哪個課程 班級的連結
這個作業要求在哪裡 作業要求的連結
這個作業的目標 實現論文查重演算法,並對程式碼進行效能分析、單元測試,使用PSP表

GitHub連結

一、PSP表

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 15 20
Estimate 估計這個任務需要多少時間 15 30
Development 開發 150 210
Analysis 需求分析 (包括學習新技術) 30 50
Design Spec 生成設計文件 60 80
Design Review 設計複審 20 30
Coding Standard 程式碼規範 (為目前的開發制定合適的規範) 15 15
Design 具體設計 25 20
Coding 具體編碼 30 150
Code Review 程式碼複審 30 40
Test 測試(自我測試,修改程式碼,提交修改) 30 50
Reporting 報告 40 60
Test Repor 測試報告 20 25
Size Measurement 計算工作量 15 15
Postmortem & Process Improvement Plan 事後總結,並提出過程改進計劃 40 40
合計 535 835

二、計算模組的設計與實現

1、總體設計

目錄表:

流程圖

2、詳細設計

DataPreprocessing類

read_file 函式:讀取檔案資料,發生異常則丟擲對應的異常並返回-1。
preprocess_data 函式:對資料進行全形轉半形、去除HTML標籤、保留中文字元操作,發生異常則丟擲對應的異常並返回空字元.
to_dbc 函式:對資料進行全形轉半形操作。

SimHashService類

get函式:使用jieba分詞,過濾標點符號或無效字元,過濾標點符號或無效字元,按權重逐位計算雜湊值,將統計結果轉換成0/1字串。

關鍵演算法流程圖!
get_word_hash 函式:計算詞雜湊值。
get_word_weight 函式:定義詞的權重。
hamming_distance 函式:計算漢明距離。

SimilarityChecker類:

check_similarity函式:計算兩篇文章的SimHash後計算漢明距離,根據漢明距離計算論文相似度。

三、效能改進

1、效能分析

這裡我使用PyCharm自帶的Profile功能進行效能分析。

從上圖中可以看到耗時最長的是隻執行一次的Python內建的,而我編寫的程式碼耗時最長的是get函式,執行10914次,耗時2ms。

2、改進思路

可以增加對生成processed_text1, processed_text2的合理性判斷,減少 checker.check_similarity方法的呼叫,因為get方法耗時很長,而get方法就是checker.check_similarity呼叫的。

四、單元測試

思路:

使用unittest庫,共設計25個函式(分4個類TestDataPreprocessing、TestGetWordHash、TestHammingDistance、TestSimilarityChecker)來對6個關鍵函式進行測試,儘可能地對我所構建的論文查重演算法進行測試,保證程式碼健壯性、準確性、通用性。

資料預處理單元測試程式碼展示:

    def test_preprocess_data_with_valid_input(self):
        """測試 preprocess_data 方法,包含 HTML 標籤和非中文字元"""
        text_content = "<html>這是一個測試! 123</html>"
        result = DataPreprocessing.preprocess_data(text_content)
        expected = "這是一個測試"  # 去除HTML標籤和非中文字元後的結果
        self.assertEqual(result, expected)

    def test_preprocess_data_with_empty_input(self):
        """測試 preprocess_data 方法,輸入為空字串"""
        text_content = ""
        result = DataPreprocessing.preprocess_data(text_content)
        self.assertEqual(result, "")

    def test_preprocess_data_with_all_non_chinese(self):
        """測試 preprocess_data 方法,輸入不包含中文字元"""
        text_content = "Hello, World! 123"
        result = DataPreprocessing.preprocess_data(text_content)
        self.assertEqual(result, "")

    def test_to_dbc_with_full_width_characters(self):
        """測試 to_dbc 方法,將全形字元轉換為半形"""
        input_str = "ABCabc123!@#"
        result = DataPreprocessing.to_dbc(input_str)
        expected = "ABCabc123!@#"
        self.assertEqual(result, expected)

    def test_to_dbc_with_mixed_characters(self):
        """測試 to_dbc 方法,混合全形和半形字元"""
        input_str = "Hello ABC"
        result = DataPreprocessing.to_dbc(input_str)
        expected = "Hello ABC"
        self.assertEqual(result, expected)

    def test_read_file(self):
        """測試 read_file 方法"""
        file_path = "D:\PyCharmCode\SimHash\\3122004446\DataSet\測試用例\DataPreprocessing.txt"
        result = DataPreprocessing.read_file(file_path)
        expected = "《軟 件工程!,123"
        self.assertEqual(result, expected)

    def test_read_file_err1(self):
        """測試 read_file 方法 不存在次檔案"""
        file_path = "D:\PyCharmCode\SimHash\\3122004446\DataSet\測試用例\DataPreprocessing_err1.txt"
        result = DataPreprocessing.read_file(file_path)
        # print(f"result7:{result}")
        expected = -1
        self.assertEqual(result, expected)

單元測試結果截圖

覆蓋率

這裡使用Python的coverage庫進行分析。
程式碼檔案覆蓋率截圖:

各個函式覆蓋率截圖:

各個類覆蓋率截圖:

五、異常處理

這裡我用unittest庫對各個單元進行異常測試。

異常一

read_file函式異常:在讀取檔案時找不到目標檔案或無法正常開啟目標檔案時,異常時丟擲異常提示並返回-1。
測試樣例:

    def test_read_file_err1(self):
        """測試 read_file 方法 不存在次檔案"""
        file_path = "D:\PyCharmCode\SimHash\\3122004446\DataSet\測試用例\DataPreprocessing_err1.txt"
        result = DataPreprocessing.read_file(file_path)
        # print(f"result7:{result}")
        expected = -1
        self.assertEqual(result, expected)

結果截圖:

異常二

to_dbc函式異常:當非字串輸入、非常大的字串、特殊字元、外部環境問題、編碼問題時,異常時丟擲異常提示並返回輸入內容。
測試樣例:

class TestDataPreprocessing(unittest.TestCase):
    def test_to_dbc_with_mixed_characters(self):
        """測試 to_dbc 方法,混合全形和半形字元"""
        input_str = None
        result = DataPreprocessing.to_dbc(input_str)
        expected = None
        self.assertEqual(result, expected)

結果截圖:

異常三

get_word_hash函式:當非字串輸入、索引越界、特殊字元、編碼問題、極端長度的字串時,異常時丟擲異常提示並返回0。
測試樣例:

class TestGetWordHash(unittest.TestCase):
    def test_empty_string(self):
        # 測試空字串輸入
        result = SimHashService.get_word_hash(123)
        self.assertEqual(result, BIGINT_0)

結果截圖:

異常四

get_word_weight函式:當輸入數字時,丟擲異常提示並返回0。
測試樣例:

class TestGetWordHash(unittest.TestCase):
    def test_empty_string(self):
        # 測試空字串輸入
        result = SimHashService.get_word_weight(111)
        self.assertEqual(result, BIGINT_0)

結果截圖:

異常五

hamming_distance函式:當輸入的值不是字串時,丟擲異常提示並返回-1。
測試樣例:

class TestHammingDistance(unittest.TestCase):
    def test_both_none(self):
        # 測試兩個輸入都為 None
        result = SimHashService.hamming_distance("110", 110)
        self.assertEqual(result, -1)

結果截圖:

六、總結

這是我第一次按照PSP表寫的程式,從前期的預估安排時間、學習新知識,到期間的編寫程式,再到後期測試程式與撰寫報告。體會到了PSP表對於提高軟體開發人員個人生產效率和產品質量的作用,也接觸到了unittest、coverage、profile等測試分析的方法,是一次難忘的程式設計經理。

相關文章