Skip to content

[feat] add pytest-cov coverage gate to CI - #13

Merged
h1s97x merged 1 commit into
mainfrom
feature/add-coverage-gate
May 16, 2026
Merged

[feat] add pytest-cov coverage gate to CI#13
h1s97x merged 1 commit into
mainfrom
feature/add-coverage-gate

Conversation

@h1s97x

Copy link
Copy Markdown
Owner

变更内容

CI 改进

在 test job 中添加 pytest-cov:

Looking in indexes: https://mirrors.aliyun.com/pypi/simple/
Requirement already satisfied: pytest in /usr/local/lib/python3.12/dist-packages (8.4.2)
Requirement already satisfied: pytest-cov in /usr/local/lib/python3.12/dist-packages (7.0.0)
Requirement already satisfied: iniconfig>=1 in /usr/local/lib/python3.12/dist-packages (from pytest) (2.3.0)
Requirement already satisfied: packaging>=20 in /usr/local/lib/python3.12/dist-packages (from pytest) (25.0)
Requirement already satisfied: pluggy<2,>=1.5 in /usr/local/lib/python3.12/dist-packages (from pytest) (1.6.0)
Requirement already satisfied: pygments>=2.7.2 in /usr/local/lib/python3.12/dist-packages (from pytest) (2.20.0)
Requirement already satisfied: coverage>=7.10.6 in /usr/local/lib/python3.12/dist-packages (from coverage[toml]>=7.10.6->pytest-cov) (7.13.5)
============================= test session starts ==============================
platform linux -- Python 3.12.3, pytest-8.4.2, pluggy-1.6.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /workspace/projects
configfile: pyproject.toml
plugins: anyio-4.13.0, langsmith-0.4.39, asyncio-1.3.0, cov-7.0.0, mock-3.15.1, typeguard-4.5.1
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collecting ... collected 77 items

tests/unit/test_crypto1.py::TestCrypto1Tools::test_int_to_bit_str PASSED [ 1%]
tests/unit/test_crypto1.py::TestCrypto1Tools::test_bit_str_to_int PASSED [ 2%]
tests/unit/test_crypto1.py::TestCrypto1Tools::test_bit_str_to_int_list PASSED [ 3%]
tests/unit/test_crypto1.py::TestCrypto1Tools::test_int_list_to_bit_str PASSED [ 5%]
tests/unit/test_crypto1.py::TestCrypto1FilterFunctions::test_fa_function PASSED [ 6%]
tests/unit/test_crypto1.py::TestCrypto1FilterFunctions::test_fb_function PASSED [ 7%]
tests/unit/test_crypto1.py::TestCrypto1FilterFunctions::test_fc_function PASSED [ 9%]
tests/unit/test_crypto1.py::TestCrypto1LFSR::test_left_one PASSED [ 10%]
tests/unit/test_crypto1.py::TestCrypto1LFSR::test_lfsr_feedback_calculation PASSED [ 11%]
tests/unit/test_crypto1.py::TestCrypto1LFSR::test_lfsr_initialization PASSED [ 12%]
tests/unit/test_crypto1.py::TestCrypto1KeyStream::test_keystream_length PASSED [ 14%]
tests/unit/test_crypto1.py::TestCrypto1KeyStream::test_keystream_deterministic PASSED [ 15%]
tests/unit/test_crypto1.py::TestCrypto1EncryptDecrypt::test_xor_symmetry PASSED [ 16%]
tests/unit/test_crypto1.py::TestCrypto1EncryptDecrypt::test_encrypt_decrypt_property PASSED [ 18%]
tests/unit/test_ecc.py::TestECCUtils::test_str_add_space_empty PASSED [ 19%]
tests/unit/test_ecc.py::TestECCUtils::test_str_add_space_even_length PASSED [ 20%]
tests/unit/test_ecc.py::TestECCUtils::test_str_add_space_odd_length PASSED [ 22%]
tests/unit/test_ecc.py::TestECCUtils::test_str_add_space_single_pair PASSED [ 23%]
tests/unit/test_ecc.py::TestECCUtils::test_str_add_space_already_spaced PASSED [ 24%]
tests/unit/test_ecc.py::TestECCKeyGeneration::test_ecc_generate_keys PASSED [ 25%]
tests/unit/test_ecc.py::TestECCKeyGeneration::test_ecc_keys_are_unique PASSED [ 27%]
tests/unit/test_ecc.py::TestECCEncryption::test_ecc_encrypt_produces_ciphertext PASSED [ 28%]
tests/unit/test_ecc.py::TestECCEncryption::test_ecc_encrypt_different_plaintexts PASSED [ 29%]
tests/unit/test_ecc.py::TestECCEncryption::test_ecc_encrypt_different_keys PASSED [ 31%]
tests/unit/test_ecc.py::TestECCDecryption::test_ecc_decrypt_returns_original_plaintext PASSED [ 32%]
tests/unit/test_ecc.py::TestECCDecryption::test_ecc_decrypt_various_lengths PASSED [ 33%]
tests/unit/test_ecc.py::TestECCDecryption::test_ecc_ciphertext_structure PASSED [ 35%]
tests/unit/test_euclidean.py::TestGCD::test_gcd_same_number PASSED [ 36%]
tests/unit/test_euclidean.py::TestGCD::test_gcd_coprime PASSED [ 37%]
tests/unit/test_euclidean.py::TestGCD::test_gcd_common_divisor PASSED [ 38%]
tests/unit/test_euclidean.py::TestGCD::test_gcd_zero PASSED [ 40%]
tests/unit/test_euclidean.py::TestGCD::test_gcd_large_numbers PASSED [ 41%]
tests/unit/test_euclidean.py::TestGCD::test_gcd_prime_numbers PASSED [ 42%]
tests/unit/test_sm2_sign.py::TestSM2Sign::test_generate_keypair PASSED [ 44%]
tests/unit/test_sm2_sign.py::TestSM2Sign::test_sign_and_verify PASSED [ 45%]
tests/unit/test_sm2_sign.py::TestSM2Sign::test_sign_different_messages PASSED [ 46%]
tests/unit/test_sm2_sign.py::TestSM2Sign::test_verify_wrong_signature PASSED [ 48%]
tests/unit/test_sm2_sign.py::TestSM2Sign::test_verify_wrong_message PASSED [ 49%]
tests/unit/test_sm2_sign.py::TestSM2Sign::test_sign_with_different_keys PASSED [ 50%]
tests/unit/test_type_convert.py::TestIsHexString::test_valid_hex_lowercase PASSED [ 51%]
tests/unit/test_type_convert.py::TestIsHexString::test_valid_hex_uppercase PASSED [ 53%]
tests/unit/test_type_convert.py::TestIsHexString::test_valid_hex_mixed PASSED [ 54%]
tests/unit/test_type_convert.py::TestIsHexString::test_invalid_hex_with_space PASSED [ 55%]
tests/unit/test_type_convert.py::TestIsHexString::test_invalid_hex_with_g PASSED [ 57%]
tests/unit/test_type_convert.py::TestIsHexString::test_invalid_hex_with_z PASSED [ 58%]
tests/unit/test_type_convert.py::TestIsHexString::test_empty_string PASSED [ 59%]
tests/unit/test_type_convert.py::TestStrToHexList::test_valid_hex_string PASSED [ 61%]
tests/unit/test_type_convert.py::TestStrToHexList::test_valid_hex_string_with_spaces PASSED [ 62%]
tests/unit/test_type_convert.py::TestStrToHexList::test_odd_length_returns_error PASSED [ 63%]
tests/unit/test_type_convert.py::TestStrToHexList::test_invalid_character_returns_error PASSED [ 64%]
tests/unit/test_type_convert.py::TestIntToStr::test_small_number PASSED [ 66%]
tests/unit/test_type_convert.py::TestIntToStr::test_zero PASSED [ 67%]
tests/unit/test_type_convert.py::TestIntToStr::test_max_bytes PASSED [ 68%]
tests/unit/test_type_convert.py::TestHexListToStr::test_valid_hex_list PASSED [ 70%]
tests/unit/test_type_convert.py::TestHexListToStr::test_empty_list PASSED [ 71%]
tests/unit/test_type_convert.py::TestStrToInt::test_valid_hex_string PASSED [ 72%]
tests/unit/test_type_convert.py::TestStrToInt::test_valid_hex_string_with_spaces PASSED [ 74%]
tests/unit/test_type_convert.py::TestStrToInt::test_odd_length_returns_none PASSED [ 75%]
tests/unit/test_type_convert.py::TestIntToHexList::test_small_number PASSED [ 76%]
tests/unit/test_type_convert.py::TestIntToHexList::test_zero PASSED [ 77%]
tests/unit/test_type_convert.py::TestIntToHexList::test_exact_length PASSED [ 79%]
tests/unit/test_zuc.py::TestZUCTools::test_mod_normal PASSED [ 80%]
tests/unit/test_zuc.py::TestZUCTools::test_mod_overflow PASSED [ 81%]
tests/unit/test_zuc.py::TestZUCTools::test_mod_zero PASSED [ 83%]
tests/unit/test_zuc.py::TestZUCTools::test_mul_by_pow2_normal PASSED [ 84%]
tests/unit/test_zuc.py::TestZUCTools::test_mul_by_pow2_zero PASSED [ 85%]
tests/unit/test_zuc.py::TestZUCTools::test_l1_function PASSED [ 87%]
tests/unit/test_zuc.py::TestZUCTools::test_l2_function PASSED [ 88%]
tests/unit/test_zuc.py::TestZUCTools::test_rotl_uint32_normal PASSED [ 89%]
tests/unit/test_zuc.py::TestZUCTools::test_rotl_uint32_full PASSED [ 90%]
tests/unit/test_zuc.py::TestZUCTools::test_rotl_uint32_zero PASSED [ 92%]
tests/unit/test_zuc.py::TestZUCClass::test_zuc_initialization PASSED [ 93%]
tests/unit/test_zuc.py::TestZUCClass::test_zuc_lfsr_state PASSED [ 94%]
tests/unit/test_zuc.py::TestZUCClass::test_zuc_key_different PASSED [ 96%]
tests/unit/test_zuc.py::TestZUCClass::test_zuc_iv_different PASSED [ 97%]
tests/unit/test_zuc.py::TestZUCClass::test_zuc_generate_keystream PASSED [ 98%]
tests/unit/test_zuc.py::TestZUCClass::test_zuc_encrypt_decrypt PASSED [100%]

================================ tests coverage ================================
_______________ coverage: platform linux, python 3.12.3-final-0 ________________

Name Stmts Miss Cover

core/init.py 0 0 100%
core/algorithms/init.py 0 0 100%
core/algorithms/asymmetric/ECC.py 61 7 89%
core/algorithms/asymmetric/ECDSA.py 56 56 0%
core/algorithms/asymmetric/ElGamal.py 111 111 0%
core/algorithms/asymmetric/RSA.py 74 74 0%
core/algorithms/asymmetric/RSA_Sign.py 128 128 0%
core/algorithms/asymmetric/SM2.py 115 115 0%
core/algorithms/asymmetric/SM2_Sign.py 93 93 0%
core/algorithms/asymmetric/init.py 0 0 100%
core/algorithms/classical/Caesar.py 88 88 0%
core/algorithms/classical/Enigma.py 212 212 0%
core/algorithms/classical/Frequency_Analysis.py 110 110 0%
core/algorithms/classical/Hill.py 138 138 0%
core/algorithms/classical/Monoalphabetic_Cipher.py 103 103 0%
core/algorithms/classical/Playfair.py 173 173 0%
core/algorithms/classical/Vigenere.py 92 92 0%
core/algorithms/classical/init.py 0 0 100%
core/algorithms/hash/AES_CBC_MAC.py 38 38 0%
core/algorithms/hash/HMAC_MD5.py 71 71 0%
core/algorithms/hash/Hash_Reverse.py 36 36 0%
core/algorithms/hash/MD5.py 74 74 0%
core/algorithms/hash/SHA1.py 134 134 0%
core/algorithms/hash/SHA3.py 158 158 0%
core/algorithms/hash/SHA256.py 103 103 0%
core/algorithms/hash/SM3.py 155 155 0%
core/algorithms/hash/init.py 0 0 100%
core/algorithms/mathematical/CRT.py 41 41 0%
core/algorithms/mathematical/Euclidean.py 19 7 63%
core/algorithms/mathematical/Euler.py 48 48 0%
core/algorithms/mathematical/init.py 0 0 100%
core/algorithms/symmetric/AES.py 198 198 0%
core/algorithms/symmetric/Block_Mode.py 116 116 0%
core/algorithms/symmetric/Crypto_1.py 138 85 38%
core/algorithms/symmetric/DES.py 180 180 0%
core/algorithms/symmetric/RC4.py 85 85 0%
core/algorithms/symmetric/SEAL.py 230 230 0%
core/algorithms/symmetric/SIMON.py 254 254 0%
core/algorithms/symmetric/SM4.py 119 119 0%
core/algorithms/symmetric/SPECK.py 248 248 0%
core/algorithms/symmetric/ZUC.py 180 70 61%
core/algorithms/symmetric/init.py 0 0 100%
core/interfaces/init.py 0 0 100%
core/validators/init.py 0 0 100%
infrastructure/ModularPower.py 31 31 0%
infrastructure/Path.py 70 70 0%
infrastructure/Verify.py 127 127 0%
infrastructure/init.py 0 0 100%
infrastructure/converters/TypeConvert.py 102 25 75%
infrastructure/converters/init.py 0 0 100%
infrastructure/logging/init.py 0 0 100%
infrastructure/security/PrimeGen.py 80 80 0%
infrastructure/security/init.py 0 0 100%
infrastructure/threading/init.py 0 0 100%

TOTAL 4589 4283 7%
Required test coverage of 5% reached. Total coverage: 6.67%
============================== 77 passed in 0.94s ==============================

功能

  • 覆盖率报告: 生成详细的覆盖率报告,显示未覆盖的代码行
  • 覆盖率门槛: 设置最低覆盖率要求 5%
  • 覆盖率统计: core 和 infrastructure 模块

覆盖率目标

阶段门槛说明
当前5%初始门槛,确保 CI 稳定
下一阶段10%测试覆盖增加后提高
长期目标30%+核心算法全覆盖

验证

  • 本地覆盖率检查通过 (7% > 5%)
  • 77 个测试全部通过

- Add pytest-cov to test dependencies
- Run tests with coverage report: --cov=core --cov=infrastructure
- Set minimum coverage threshold: 5% (--cov-fail-under=5)
- Generate coverage report with missing lines
Note: Coverage threshold starts at 5% and will increase as more tests are added.
@h1s97x
h1s97x merged commit cab1140 into mainMay 16, 2026
3 checks passed
@h1s97x
h1s97x deleted the feature/add-coverage-gate branch May 16, 2026 15:06
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@h1s97x