测试过程分析
1.单元测试 (Unit Testing): 这种测试关注于最小的代码单元(通常是函数或方法)。目的是验证每个单元按预期工作。单元测试通常由开发者编写,使用如JUnit或PyTest等工具自动执行。
2.功能测试 (Functional Testing): 功能测试关注于软件的特定功能或功能组。它验证软件的功能是否符合需求规格。这种测试通常由测试团队执行,可以手动或自动进行。
3.集成测试 (Integration Testing): 集成测试验证多个组件或系统的组合是否能够正确协同工作。例如,测试数据库与应用服务器的交互。
4.压力测试 (Stress Testing): 压力测试旨在确定软件在超过正常或峰值负载条件下的行为。它帮助识别软件的弱点和性能瓶颈。
5.回归测试 (Regression Testing): 每当代码发生变化时,回归测试确保这些变化没有破坏现有的功能。这通常在软件更新后自动执行,以确保新代码没有引入新的错误。
黑箱测试与白箱测试
黑箱测试 (Black Box Testing): 在黑箱测试中,测试人员不需要了解内部代码结构或程序的内部工作原理。测试是基于需求和功能的。测试者只关注输入和输出,验证功能是否符合预期。
白箱测试 (White Box Testing): 与黑箱测试相对,白箱测试需要测试者了解内部代码逻辑和结构。这通常由开发人员进行,目的是检查代码中的每个分支、循环和条件语句,确保所有路径都经过测试。
数据构造策略
边界值分析: 选取输入值的边界点进行测试,包括最大值、最小值、零、负值等。
等价划分: 将所有可能的输入数据分为若干"等价类",每个类中的数据应该被程序同等对待。从每个等价类中选取代表性的值进行测试。
错误猜测: 基于经验选择那些可能会引发错误的特殊输入值进行测试。
架构设计
没有实现并查集,图都是暴力存储
Network类中含有people和消息的队列。
public MyNetwork() {
people = new ArrayList<>();
messages = new ArrayList<>();
emojiIdList = new ArrayList<>();
emojiHeatList = new ArrayList<>();
}
MyPerson 类表示图中的一个节点,每个节点都有一个 ID、姓名、年龄、一个熟人列表和一个值列表。MyTag 类表示图中的一个标签,每个标签都有一个 ID 和一个与之关联的人的列表。MyNetwork 类表示整个图,它包含一个 Person 对象列表、一个 Message 对象列表、一个表情 ID 列表和一个表情热度列表。MyNetwork 类中的方法用于添加或删除节点、标签、消息,以及更新它们之间的关系。MyPerson 类中的方法用于添加或删除熟人和更新值。MyTag 类中的方法用于添加与此标签关联的人。
People:
private final int id;
private final String name;
private final int age;
private final ArrayList<Person> acquaintance;
private final ArrayList<Integer> value;
private final ArrayList<Tag> tags;
private int money;
private int socialValue;
private final ArrayList<Message> messages;
Tag:
private int id;
private ArrayList<Person> people;
性能问题
在hw9实现isCircle方法时,我使用了递归深搜。在图较大时很容易爆tle(:。
public boolean dfs(MyPerson person1, MyPerson person2, boolean[] visited) {
visited[getIndex(person1)] = true;
if (person1.equals(person2)) {
return true;
}
ArrayList<Person> acquaintance = person1.getALLAcquaintance();
for (int i = 0; i < acquaintance.size(); i++) {
MyPerson myPerson = (MyPerson) acquaintance.get(i);
if (!visited[getIndex(myPerson)] && dfs(myPerson, person2, visited)) {
return true;
}
}
visited[getIndex(person1)] = false;
return false;
}
@Override
public boolean isCircle(int id1, int id2) throws PersonIdNotFoundException {
if (!containsPerson(id1)) {
throw new MyPersonIdNotFoundException(id1);
} else if (!containsPerson(id2)) {
throw new MyPersonIdNotFoundException(id2);
}
boolean[] visited = new boolean[people.size() + 1];
return dfs((MyPerson) getPerson(id1), (MyPerson) getPerson(id2), visited);
}
public boolean isCircle2(int id1, int id2) {
boolean[] visited = new boolean[people.size() + 1];
return dfs((MyPerson) getPerson(id1), (MyPerson) getPerson(id2), visited);
}
由于没有使用并查集构建图,后续最短路径等算法也直接BFS没有进行优化。
规格和实现分离
规格指定了Java程序中的类和接口的规范。本单元作业中,由于课程组给定了类和方法的具体信息而无需自己设计架构,根据课程组给定的JML实现对应的java代码相对容易。而且通过JML能够保证自己编写的程序是正确的。
Junit测试
本单元要求使用Junit对错误代码按照规格进行测试。因此在编写Junit代码时,需要严格测试规格的一致性。主要要注意测试的完备性。即规格的前置条件,后置条件,测试不变量,异常条件,边界行为都需要进行测试。
学习体会
1.初次接触JML,规格化的方法确实利于编写出正确的程序。
2.接触junit单元测试,通过对自己的程序进行测试更加深入的认识到了单元测试的意义。