🤔 Vistor Counter
haventong / meethere-backend Goto Github PK
View Code? Open in Web Editor NEWThe final project for software testing:fire:
The final project for software testing:fire:
我们的系统允许管理员在后台人工添加新的场馆,同时上传场馆配图。由于前段采用了上传转换后的 Base64 数据,因此后端必须对 Base64 数据进行处理。搜索资料后,后端决定使用 Java8 自带的 Base64 工具库,只需要 import java.util.Base64;
即可。但是当我们尝试:
byte[] decodedImg = Base64.getDecoder().decode(encodedImg.getBytes(StandardCharsets.UTF_8));
时,后端提示错误,无法解析。
在经过性能测试后,我们发现系统在高并发场景下存在严重的性能缺陷。如图所示,是从测试结果中所统计得出的平均响应时间:
Average Response Time (ms)
场景 | 1 | 10 | 20 | 50 | 100 | 200 |
登录 | 177.68 | 997.56 | 1904.45 | 4904.39 | 9917.64 | 18165.41 |
获取新闻 | 160.81 | 296.91 | 498.67 | 1280.95 | 2724.41 | 9354.38 |
浏览场馆/浏览评论 | 88.42 | 289.26 | 497.21 | 1325.76 | 2996.91 | 5592.29 |
浏览场馆/预定场馆 | 139.90 | 276.63 | 498.81 | 1334.04 | 2528.29 | 5927.28 |
个人信息管理 | 182.55 | 946.45 | 1802.45 | 4577.84 | 9381.85 | 19768.66 |
登录->浏览新闻->浏览场馆->预定场馆->修改个人信息 | 101.18 | 764.15 | 1497.49 | 3840.91 | 9191.59 | 12078.53 |
登录->浏览场馆->预定场馆 | 216.26 | 485.83 | 915.81 | 2326.19 | 5609.73 | 9999.62 |
登录->浏览新闻->修改密码->修改个人信息 | 216.26 | 485.83 | 915.81 | 2326.19 | 5609.73 | 9999.62 |
登录->浏览新闻->浏览场馆->发布评论 | 66.46 | 525.51 | 1342.56 | 3929.27 | 8295.51 | 12888.50 |
在我们的需求中,管理员需要能够对场馆进行管理,可以查看每个场馆的空闲时间。但在测试管理员获取场馆空闲时间的方法时,发现了bug:
如果某个场馆被预约的时间为[8:00 - 9:00, 10:00-11:00...]这样连续的时间段,本应该空闲时间包含时间段[9:00 - 10:00],然而后端返回的结果却不包含该时间段。导致该问题的原因应该是后端获取空闲时间的函数实现出现了问题。
于是重新review了后端代码,选取了新的实现方式,修改了该缺陷:
public List<String> getSpareTimeFromBookingList(List<Booking> bookingList,
LocalDate date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
List<String> spareTime = new ArrayList<>();
// timeSlotTable为一个flag数组,表示该时间槽是否被预约,每小时算一个时间槽
// e.g. timeSlotTable[0] -> 8:00-9:00,共12个
boolean[] timeSlotTable = new boolean[12];
for (boolean used : timeSlotTable) {
used = false;
}
// 只考虑一天内的预约
for (Booking booking : bookingList) {
LocalDateTime startTime = booking.getStartTime();
if (date.isEqual(startTime.toLocalDate())) {
int start = startTime.getHour();
int end = booking.getEndTime().getHour();
for (int i = start; i < end; i++) {
timeSlotTable[i - 8] = true;
}
}
}
int startIndex = (timeSlotTable[0]) ? 0 : -1;
int endIndex = 0;
for (int i = 1; i <= 11; i++) {
// 若全部空闲则循环没有操作
if (timeSlotTable[i]) {
if (!timeSlotTable[i - 1]) {
endIndex = i;
StringBuilder builder = new StringBuilder();
LocalTime startTime = LocalTime.of(startIndex + 9, 0);
LocalTime endTime = LocalTime.of(endIndex + 8, 0);
builder.append(formatter.format(startTime))
.append("-")
.append(formatter.format(endTime));
spareTime.add(builder.toString());
}
if (i <= 10 && !timeSlotTable[i + 1]) {
startIndex = i;
}
}
}
if (!timeSlotTable[11]) {
StringBuilder builder = new StringBuilder();
LocalTime startTime = LocalTime.of(startIndex + 9, 0);
builder.append(formatter.format(startTime))
.append("-")
.append("20:00");
spareTime.add(builder.toString());
}
return spareTime;
}
我们规定允许用户的手机号为空,且用户手机号默认为空。但是在进行系统测试时,发现了一个问题。
我们在前后端分别为手机号格式进行了校验,必须满足**大陆的手机号格式。我们通过正则表达式来匹配手机号的格式,若匹配则允许进行操作。
但是,当前端将手机号设置为空时,后端不允许进行相应的操作。查看后端报错信息后,我们发现,后端在进行
参数校验时忽略了手机号为空的情况,而是仅仅考虑到了手机号不为空时的匹配模式:
@Pattern(regexp = "^(1([34578])\\d{9}$", message = "手机号码格式错误")
private String phoneNumber;
这里我们修改了手机号的正则表达式,使之在进行参数校验时允许手机号为空。
@Pattern(regexp = "(^$|^(1([34578])\\d{9}))$", message = "手机号码格式错误")
private String phoneNumber;
通过这样的修改,修复了手机号校验的问题。
在进行集成测试时,我们可能需要对数据库进行删除一些数据的测试,开始时,我们写的测试开始并没有事先向数据库中添加数据,导致我们的测试用例只能被执行一次,无法多次执行。
之后我们想到可以每次执行前手动向数据库中添加数据,但是这仍然很复杂,但是使用系统已经实现的接口无法很好的添加数据,例如删除订单的集成测试,无法通过已经写好的系统功能添加好合适的订单,然后给测试用例获取删除。
我们的最终解决办法时在 Dao 层添加一些专门为测试使用的接口,来实现对数据库插入一些合适的数据,同时可以返回一些测试用例需要的数据,来供测试用例使用,实现测试用例;这样我们的测试用例就会具有了可重复执行的能力。
Dao 层部分接口代码:
@Delete("DELETE a FROM booking a, (SELECT MAX(booking_id) AS max_id FROM booking) b WHERE booking_id = b.max_id")
int deleteLatestBooking();
@Select("SELECT * FROM booking WHERE booking_id = (SELECT MAX(booking_id) FROM booking)")
Booking getLatestBooking();
@Select("SELECT COUNT(*) FROM booking")
int getAllBookingCount();
其中删除订单的集成测试代码如下:
@Test
@DisplayName("用户删除订单时,若HTTP头部携带的TOKEN与customerId匹配,返回正常结果")
void shouldDeleteBookingByCustomerWithCorrectToken() {
Booking booking = Booking.builder().customerId(507).stadiumId(1).startTime(LocalDateTime.now()).endTime(LocalDateTime.now()).paid(false).priceSum(BigDecimal.valueOf(0)).build();
bookingDao.addNewBooking(booking);
Integer bookingId = booking.getBookingId();
BookingRequest bookingRequest = BookingRequest.builder().customerId(507).bookingId(bookingId).build();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("TOKEN", "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI1MDciLCJpYXQiOjE1Nzc0NTQ0NDMsImV4cCI6MTU3OTUyODA0M30.iT_dyXZ13mqjND1XfDNqvELEWwvgusJwp6mHUmLKNmo");
HttpEntity<BookingRequest> entity = new HttpEntity<>(bookingRequest, httpHeaders);
ResponseEntity<ResultEntity> response = testRestTemplate.postForEntity(BASE_URL + "/delete-by-customer", entity, ResultEntity.class);
ResultEntity result = response.getBody();
assertAll(
() -> assertEquals(200, response.getStatusCodeValue()),
() -> assertEquals(0, result.getCode()),
() -> assertEquals("success", result.getMessage())
);
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.