身份证

身份证格式

身份证为18位,构成规则如下:

  • 前6位表示出生地所在县(市、区)
  • 7~14位表示出生年月日
  • 15~17位表示顺序码,对同地区、同年同月同日出生的人进行排序,其中第17位奇数分给男性,偶数分给女性
  • 第18位为校验码,校验码如果出现数字10,用X来表示

校验码生成

  1. 将身份证号码的前17位分别乘以不同的系数。从第1位到第17位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
  2. 将这17位数字和系数相乘的结果相加。
  3. 将相加得到的和除以11,取余数,余数只可能为0~10,分别对应身份证最后一位:1-0-X-9-8-7-6-5-4-3-2。

Python检验校验码

factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
verify_list = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
number = input()
checksum = 0
for i in range(len(number) - 1):
    checksum = checksum + factor[i] * int(number[i])
checksum = checksum % 11
print(verify_list[checksum])
if number[-1] == verify_list[checksum]:
    print("Pass")
else:
    print("Fail")

合法地区列表

  • 11:北京,12:天津,13:河北,14:山西,15:内蒙古;
  • 21:辽宁,22:吉林,23:黑龙江;
  • 31:上海,32:江苏,33:浙江,34:安徽,35:福建,36:江西,37:山东;
  • 41:河南,42:湖北,43:湖南,44:广东,45:广西,46:海南;
  • 50:重庆,51:四川,52:贵州,53:云南,54:西藏;
  • 61:陕西,62:甘肃,63:青海,64:宁夏,65:新疆;
  • 71:台湾;
  • 81:香港,82:澳门;
  • 91:国外。

测试点

不仅需要测试是否对身份证号的这些字段有校验,还需要测试是否将合法的证件号识别为非法。
因为证件号的校验过程中,可能还会因校验代码某处出错,导致合法证件号不通过的情况,这些情况所需要构造的测试输入较多。
与将非法的证件号识别为合法相比,将合法的证件号识别为非法风险更大,所以需要进行测试覆盖。

地区

合法地区列表取边界值
通过:11、15、21、23、31、37、41、46、50、54、61、65、71、81、82、91
不通过:00、01、09、10、16、20、24、30、38、40、47、55、60、66、70、72、80、83、90、92
对第3-6位不做校验,采取随机数生成的方式

出生年份

1900-当前年份取边界值
通过:1900、1999、2000、2001、当前年份(小于等于当前日期)
不通过:1899、2021

出生月份

01-12取边界值
通过:01、09、10、11、12
不通过:00、13

出生日期

01-31取边界值
通过:01、10、11、20、21、30、31
不通过:00、32

年月日组合

闰平年2月日期校验、每月日期校验
通过:20040229、0131、0228、0331、0430、0531、0630、0731、0831、0930、1031、1130、1231、当前日期
不通过:20010229、0132、0230、0332、0431、0532、0631、0732、0832、0931、1032、1131、1232、当前日期+1天

顺序码

000-999取边界值
通过:000、099、100、101、999

校验码

遍历0-9、X
通过:遍历0-9、X,且按照校验码计算规则生成
不通过:不按照校验码计算规则生成

用例生成

首先,测试应该验证通过的组合
除校验码外的选项进行单一选择组合
为每一个生成的结果构造身份证号,结果如下:
110692190001010004
154028199909100999
213694200010111005
233467200111201011
313659190012219990
370592199901300000
412401190008310991
467055200402291001
506681190001311017
542106199902289993
619982200003310007
656983200104300992
717280190005311008
815268199906301016
82094220000731999X
912217200108310002
112780190009300999
157117199910311004
21574119001130101X
233436199912319992
还需要额外增加一个当前日期构造的身份证号

已覆盖所有校验码的情况

然后验证应该验证不通过的组合
对于每一个非法的字段,组合其他合法的字段,并生成正确的校验码
地区非法:

  • 00821019960110000X
  • 016104199601100994
  • 090596199601101008
  • 106766199601101013
  • 161241199601109994
  • 207667199601100006
  • 248306199601100992
  • 301342199601101003
  • 380558199601101019
  • 406436199601109999
  • 479475199601100007
  • 559877199601100999
  • 604832199601101001
  • 666767199601101019
  • 708179199601109995
  • 721966199601100002
  • 800764199601100995
  • 831137199601101005
  • 908908199601101011
  • 929776199601109990

出生年份非法:

  • 119266189901100000
  • 155809202101100992

出生月份非法:

  • 216299199600101007
  • 233888199613101010

出生日期非法:

  • 312544199601009998
  • 271079199601320009
    还需要一个当前日期+1天构造的身份证号,可使用附件脚本构造

年月日组合非法:

  • 418429200102290995
  • 465225199601321002
  • 503522199602301011
  • 542888199603329990
  • 619936199604310009
  • 650394199605320993
  • 710026199606311009
  • 817812199607321011
  • 825244199608329990
  • 914952199609310004
  • 116092199610320999
  • 15948219961131100X
  • 219376199612321010

校验码非法:

  • 112409199001010005