投票系统-软件测试报告
目 录
1 作业目的与要求………………………………………………………………………………………….. 1
2 软件测试环境搭建………………………………………………………………………………………. 1
2.1 自定测试项目环境搭建………………………………………………………………………. 1
2.2 指定软件系统测试环境搭建……………………………………………………………….. 1
2.2.1 环境配置描述………………………………………………………………………………….. 2
2.2.2 搭建过程描述………………………………………………………………………………….. 2
3 软件测试过程及结果…………………………………………………………………………………… 2
3.1 白盒测试(单元测试)………………………………………………………………………. 2
3.1.1 顺序结构程序测试…………………………………………………………………………… 2
3.1.2 分支结构程序测试…………………………………………………………………………… 5
3.1.3 循环结构程序测试…………………………………………………………………………… 9
1 作业目的与要求
(1)学习软件测试的基本方法;
(2)实践软件测试的基本过程;
(3)掌握单元测试、集成测试的方法;
(4)掌握白盒测试和黑盒测试的基本方法;
(5)学习UI的基本测评和用户体验;
(6)本次作业要求主要由个人独立完成。
2 软件测试环境搭建
2.1 自定测试项目环境搭建
l 硬件环境
X64 CPU;2GHz;2G RAM;256GHD Disk 以上
l 软件环境
Windows7/10 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位 以上;
l 开发工具
IDEA
软件构造Lab3—投票系统部分代码
2.2 指定软件系统测试环境搭建
l 硬件环境
X64 CPU;2GHz;2G RAM;256GHD Disk 以上
l 软件环境
Windows7/10 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位 以上;
l 浏览器
Google浏览器
l 网络代理
EasyConnect校内网vpn
l 选取系统
哈工大统一身份认证,今日哈工大
http://ids-hit-edu-cn-s.ivpn.hit.edu.cn/
2.2.1 环境配置描述
l Windows10系统
l 校外网络,使用EasyConnect作为VPN转换为校园网络
l Google浏览器
2.2.2 搭建过程描述
l 下载安装EasyConnect
l 输入i.hit.edu.cn
l 登录学工号和密码
l 成功接入校园网VPN
3 软件测试过程及结果
3.1 白盒测试(单元测试)
3.1.1 顺序结构程序测试
3.1.1.1测试对象
源代码
\1. //immutable
\2. public class VoteType {
\3.
\4. // key**为选项名、value为选项名对应的分数
\5. private Map<String, Integer> options = new HashMap<>();
\6.
\7. // Rep Invariants
\8. // 选项名key不能为””,其中不允许出现空格
\9. *// options.size()*选项个数需要>=2
\10. // Abstract Function
\11. *// AF(String,Integer)->*选项其中key为选项名、value为选项名对应的分数
\12. // Safety from Rep Exposure
\13. // 所有的数据域都是私有的
\14. // 用Collections.unmodifiableMap()转化为不可变类型返回给外部
\15.
\16. /**
\17. *
\18. * @param options voteType对应的选项名和分数
\19. */
\20. public VoteType(Map<String,Integer> options) {
\21. this.options=new HashMap<>(options);
\22. checkRep();
\23. }
流程图
根据传入的Map,创建一个投票类型对象
图3.1.1.1流程图
3.1.1.2测试用例设计
分类 | 细则 | 样例 | |
---|---|---|---|
不存在投票选项 | 空白 | Null | |
存在投票选项 | Key符合条件 | options2.put(“喜欢”,2); options2.put(“不喜欢”,0); options2.put(“无所谓”,1); | |
Key不符合条件 | options3.put(“特别特别的喜欢”,2); options3.put(“ “,0); options3.put(“无 所 谓”,1); |
3.1.1.3测试过程与结果
测试步骤:
l Stub程序创建options
l Stub程序给定options的变量
l 利用junit进行判定
针对VoteType(Map<String,Integer> options)
1.不存在投票选项
2.存在投票选项
2.1Key符合条件
2.2Key不符合条件
结果:
3.1.1.4 Driver或Stub程序的编制
\1. /**
\2. * 针对VoteType(Map<String,Integer> options)
\3. * 1.不存在投票选项
\4. * 2.存在投票选项
\5. * 2.1Key符合条件
\6. * 2.2Key不符合条件
\7. */
\8. @Test
\9. public void VoteTypeTest_NotRegex()
\10. {
\11. Map<String, Integer> options = new HashMap<>();
\12. VoteType voteType = new VoteType(options);
\13. assertEquals(options,voteType.getOptions());
\14.
\15. Map<String, Integer> options2 = new HashMap<>();
\16. options2.put(“喜欢”,2);
\17. options2.put(“不喜欢”,0);
\18. options2.put(“无所谓”,1);
\19. VoteType voteType2 = new VoteType(options2);
\20. assertEquals(options2,voteType2.getOptions());
\21.
\22. // Map<String, Integer> options3 = new HashMap<>();
\23. *// options3.put(“*特别特别的喜欢”,2);
\24. // options3.put(“ “,0);
\25. *// options3.put(“*无 所 谓”,1);
\26. // VoteType voteType3 = new VoteType(options3);
\27. // assertFalse(false,voteType3.getOptions());
\28. }
3.1.2 分支结构程序测试
3.1.2.1测试对象
源代码
\1. public VoteType(String regex) throws IllegalArgumentException{
\2. // split**的参数是一个正则表达式,‘|’需要转义
\3. String[] inputOptions = regex.split(“\|”);
\4. *//*得到 “喜欢”(2)
\5. *//*或者得到 “支持”
\6. if(inputOptions.length < 2) {
\7. throw new IllegalArgumentException(“非法输入:选项少于两个”);
\8. }
\9. Pattern regexWithNum = Pattern.compile(“"(\S+)"\(([-]?\d+)\)”);
\10. Pattern regexWithoutNum = Pattern.compile(“"(\S+)"“);
\11. int unMatchFlag=0;*//*不匹配次数
\12. *//*先尝试匹配有数字模式
\13. for (String option : inputOptions) {
\14. Matcher m = regexWithNum.matcher(option);
\15. if(!m.matches())
\16. {
\17. unMatchFlag++;*//*若这个当前不匹配,不匹配次数+1
\18. break;
\19. }
\20. if (m.group(1).length() > 5)
\21. throw new IllegalArgumentException(“选项名长度超过5”);
\22. options.put(m.group(1), Integer.valueOf(m.group(2)));
\23. }
\24. if(unMatchFlag==0)
\25. {
\26. checkRep();
\27. return;
\28. }
\29. *//*匹配无数字的等权重格式
\30. for (String option : inputOptions) {
\31. Matcher m = regexWithoutNum.matcher(option);
\32. if(!m.matches())
\33. {
\34. unMatchFlag++;*//*若这个当前不匹配,不匹配次数+1
\35. break;
\36. }
\37. if (m.group(1).length() > 5)
\38. throw new IllegalArgumentException(“选项名长度超过5”);
\39. options.put(m.group(1), 1);
\40. }
\41. if(unMatchFlag==2)*//*代表都不匹配
\42. throw new IllegalArgumentException(“两种情况都不匹配”);
\43. checkRep();
\44. }
流程图
根据满足特定语法规则的字符串,创建一个投票类型对象
@param regex 遵循特定语法的、包含投票类型信息的字符串(待任务12再考虑)
该字符串的语法规则如下:
// “喜欢”(2)|“不喜欢”(0)|“无所谓”(1)
// 其中,用双引号括起来的文字部分是一个投票选项,长度不超过 5,其中不
// 允许出现空格;用括号括起来的数字是投票选项对应的分数,可以是正整数、0
// 或负整数,不能带小数,正整数不需要使用“+”,但负整数需要使用“-”;不同
// 的投票选项之间用“|”隔开。
// 也可以用如下形式:
// “支持”|“反对”|“弃权”
// 与上面的例子相比,区别是没有分数。这种情况表明各个投票选项的权重是一样的
图3.1.1.1流程图
3.1.2.2测试用例设计
分类 | 细则 | 样例 |
---|---|---|
匹配有数字模式 | 不含负数 | “喜欢”(2)|”不喜欢”(0)|”无所谓”(1) |
含负数 | “喜欢”(-2)|”不喜欢”(0)|”无所谓”(1) | |
匹配无数字模式 | 不超过5个长度 | “支持”|”反对”|”弃权” |
超过5个长度 | “支持”|”反对”|”弃权”|”超级支持”|”超级弃权”|”超级超级支持” | |
无法匹配正常模式 | “支持(1)”|”反对”|”弃权” |
3.1.2.3测试过程与结果
测试步骤:
l Stub程序创建options
l Stub程序给定options的变量
l 利用junit进行判定
测试成功:
1.测试带数字的
1.1不含负数
1.2含负数
2.测试不带数字的
测试抛出异常:
1,超过5个长度
2.格式不对
结果:
3.1.2.4 Driver或Stub程序的编制
\1. /**
\2. * 针对VoteType(String regex)
\3. * 测试成功:
\4. * 1.测试带数字的
\5. * 1.1不含负数
\6. * 1.2含负数
\7. * 2.测试不带数字的
\8. * 测试抛出异常:
\9. * 1,超过5个长度
\10. * 2.格式不对
\11. */
\12. @Test
\13. public void VoteTypeTest_regex()
\14. {
\15. *//“*喜欢”(2)|”不喜欢”(0)|”无所谓”(1)
\16. Map<String, Integer> options = new HashMap<>();
\17. options.put(“喜欢”,2);
\18. options.put(“不喜欢”,0);
\19. options.put(“无所谓”,1);
\20. VoteType voteType = new VoteType(“"喜欢"(2)|"不喜欢"(0)|"无所谓"(1)”);
\21. assertEquals(options,voteType.getOptions());
\22.
\23. *//“*喜欢”(-2)|”不喜欢”(0)|”无所谓”(1)
\24. Map<String, Integer> options3 = new HashMap<>();
\25. options3.put(“喜欢”,-2);
\26. options3.put(“不喜欢”,0);
\27. options3.put(“无所谓”,1);
\28. VoteType voteType3 = new VoteType(“"喜欢"(-2)|"不喜欢"(0)|"无所谓"(1)”);
\29. assertEquals(options3,voteType3.getOptions());
\30.
\31. *//“*支持”|”反对”|”弃权”
\32. *//*没有分数都默认为1
\33. Map<String, Integer> options2 = new HashMap<>();
\34. options2.put(“支持”,1);
\35. options2.put(“反对”,1);
\36. options2.put(“弃权”,1);
\37. VoteType voteType2 = new VoteType(“"支持"|"反对"|"弃权"“);
\38. assertEquals(options2,voteType2.getOptions());
\39.
\40. assertThrows(IllegalArgumentException.class,()->new VoteType(“"超级超级支持"|"反对"|"弃权"“),”选项名长度超过5”);
\41. assertThrows(IllegalArgumentException.class,()->new VoteType(“"支持"(1)|"反对"|"弃权"“),”两种情况都不匹配”);
\42. }
3.1.3 循环结构程序测试
3.1.3.1测试对象
源代码
\1. /**
\2. * 在addVote中负责检查该选票合法性并标记
\3. * @param vote 投票
\4. * @param voter 投票人
\5. */
\6. public void checkVote(Vote
\7. {
\8. Set<VoteItem
\9. for (VoteItem
\10. if(!candidates.contains(voteItem.getCandidate()))
\11. {
\12. voteIsLegal.put(vote,false);*//*包含了不在本次投票活动的候选人
\13. return;
\14. }
\15.
\16. if(!voteType.checkLegality(voteItem.getVoteValue()))
\17. {
\18. voteIsLegal.put(vote,false);*//*一张选票中出现了本次投票不允许的选项值
\19. return;
\20. }
\21.
\22. for(VoteItem
\23. {
\24. if(voteItem2!=voteItem && voteItem2.getCandidate().equals(voteItem.getCandidate()))
\25. {
\26. voteIsLegal.put(vote,false);*//*一张选票中有对同一个候选对象的多次投票
\27. return;
\28. }
\29. }
\30. }
\31. for (C candidate : candidates) {
\32. if(!vote.candidateIncluded(candidate))
\33. {
\34. voteIsLegal.put(vote,false);*//*一张选票中没有包含本次投票活动中的所有候选人
\35. return;
\36. }
\37.
\38. }
\39. *//*若都无异常
\40. voteIsLegal.put(vote,true);*//*鉴定为合法
\41. }
流程图:
图3.1.3.2.1流程图
3.1.3.2测试用例设计
checkVote****测试
四种共用不合法选票的测试
选票不合法情况:
一张选票中没有包含本次投票活动中的所有候选人
一张选票中包含了不在本次投票活动中的候选人
一张选票中出现了本次投票不允许的选项值
一张选票中有对同一个候选对象的多次投票
候选人candidate1.candidate2,candidate3,candidate4
投票人vr1,选票为空
投票人vr2,选票里candidate5,candidate1,candidate2,candidate3
投票人vr3,选票里有candidate1.candidate2,candidate3,candidate4但是出现了本次投票不允许的选项值”like”
投票人vr3,选票里有candidate1.candidate2,candidate5,candidate4
投票人vr4,选票里有candidate1.candidate2,candidate3,candidate5
分类 | 细则 | 样例 |
---|---|---|
0次循环 | 从循环入口直接跳到循环出口 | 投票人vr1,选票为空 |
1次循环 | 查找循环初始值方面的错误 | 投票人vr2,选票里candidate5,candidate1,candidate2,candidate3 |
2次循环 | 检查在多次循环时才能暴露的错误 | 投票人vr3,选票里有candidate1.candidate2,candidate3,candidate4但是出现了本次投票不允许的选项值”like” |
m次循环 | 此时的m<n,也是检查在多次循环时才能暴露的错误 | 投票人vr3,选票里有candidate1.candidate2,candidate5,candidate4 |
最大次数循环 | 投票人vr4,选票里有candidate1.candidate2,candidate3,candidate5 |
3.1.3.3测试过程与结果
测试步骤:
候选人candidate1.candidate2,candidate3,candidate4
投票人vr1,选票为空
投票人vr2,选票里candidate5,candidate1,candidate2,candidate3
投票人vr3,选票里有candidate1.candidate2,candidate3,candidate4但是出现了本次投票不允许的选项值”like”
投票人vr3,选票里有candidate1.candidate2,candidate5,candidate4
投票人vr4,选票里有candidate1.candidate2,candidate3,candidate5
l 创建投票人
l 设定投票人权重
l 设定投票类型
l 创建候选人
l 创建投票项
l 创建投票
l 创建投票活动
l 更新投票人投票
结果:
3.1.3.4 Driver或Stub程序的编制
\1. /**
\2. * 是statisticTest的检测第二种异常情况:
\3. * (也是checkVote的测试)
\4. * 四种共用不合法选票的测试
\5. * * 选票不合法情况
\6. * * ? 一张选票中没有包含本次投票活动中的所有候选人
\7. * * ? 一张选票中包含了不在本次投票活动中的候选人
\8. * * ? 一张选票中出现了本次投票不允许的选项值
\9. * * ? 一张选票中有对同一个候选对象的多次投票
\10. * 具体测试样例:
\11. *候选人candidate1.candidate2,candidate3,candidate4
\12. *投票人vr1,选票为空
\13. *投票人vr2,选票里candidate5,candidate1,candidate2,candidate3
\14. *投票人vr3,选票里有candidate1.candidate2,candidate3,candidate4但是出现了本次投票不允许的选项值”like”
\15. *投票人vr3,选票里有candidate1.candidate2,candidate5,candidate4
\16. *投票人vr4,选票里有candidate1.candidate2,candidate3,candidate5
\17. */
\18. @Test
\19. void checkVote_statistics_BuHeFaTest() {
\20. // 创建2个投票人
\21. Voter vr1 = new Voter(“v1”);
\22. Voter vr2 = new Voter(“v2”);
\23. Voter vr3 = new Voter(“v3”);
\24. Voter vr4 = new Voter(“v4”);
\25.
\26. // 设定2个投票人的权重
\27. Map<Voter, Double> weightedVoters = new HashMap<>();
\28. weightedVoters.put(vr1, 1.0);
\29. weightedVoters.put(vr2, 1.0);
\30. weightedVoters.put(vr3, 1.0);
\31. weightedVoters.put(vr4, 1.0);
\32.
\33. // 设定投票类型
\34. Map<String, Integer> types = new HashMap<>();
\35. types.put(“Support”, 1);
\36. types.put(“Oppose”, -1);
\37. types.put(“Waive”, 0);
\38. VoteType voteType = new VoteType(types);
\39.
\40. // 创建候选对象:候选人
\41. Person p1 = new Person(“candidate1”, 19);
\42. Person p2 = new Person(“candidate2”, 20);
\43. Person p3 = new Person(“candidate3”, 20);
\44. ArrayList
\45. candidates.add(p1);
\46. candidates.add(p2);
\47. // 创建投票项,前三个是投票人vr1对三个候选对象的投票项,后三个是vr2的投票项
\48. VoteItem
\49. Set<VoteItem
\50. voteItems1.add(vi11);
\51.
\52. VoteItem
\53. VoteItem
\54. Set<VoteItem
\55. voteItems2.add(vi21);
\56. voteItems2.add(vi22);
\57.
\58. VoteItem
\59. VoteItem
\60. Set<VoteItem
\61. voteItems3.add(vi31);
\62. voteItems3.add(vi32);
\63.
\64. VoteItem
\65. VoteItem
\66. Set<VoteItem
\67. voteItems4.add(vi41);
\68. voteItems4.add(vi42);
\69.
\70. // 创建2个投票人vr1、vr2的选票
\71. Vote
\72. Vote
\73. Vote
\74. Vote
\75. // System.out.println(“rv1 = “ + rv1);
\76. // System.out.println(“rv2 = “ + rv2);
\77. // 创建投票活动
\78. GeneralPollImpl
\79. // 设定投票基本信息:名称、日期、投票类型、选出的数量
\80. String name = “代表选举”;
\81. GregorianCalendar date = new GregorianCalendar(2019, 6, 14, 16, 15, 30);
\82. int quantity = 1;
\83. poll.setInfo(name, date, voteType, quantity);
\84.
\85. // 增加投票人及其权重
\86. poll.addVoters(weightedVoters);
\87. poll.addCandidates(candidates);
\88. // 增加三个投票人的选票
\89. poll.addVote(rv1, vr1);
\90. poll.addVote(rv2, vr2);
\91. poll.addVote(rv3, vr3);
\92. poll.addVote(rv4, vr4);
\93. GeneralPollImpl election = poll;
\94. Map<Vote
\95. for (Map.Entry<Vote
\96. Boolean isLegal = voteBooleanEntry.getValue();
\97. assertEquals(false, isLegal);
\98. }
\99. }