#264 - Why We Killed Our End-to-End Test Suite
Chúc các bạn có một kỳ nghỉ lễ vui vẻ bên gia đình nhé!
🗞️News
📰Những bài viết hay
Why We Killed Our End-to-End Test Suite
(by lpv)
Trước đây, tại Nubank sử dụng End-to-End test để tìm ra những vấn đề trong một kiến trúc microservices trong môi trường staging. End-to-End test có nghĩa là kích hoạt một trong các đầu vào của hệ thống (bằng cách sử dụng HTTP request hoặc tạo một message asynchronous tới một topic). Khi đó, hệ thống thường sẽ thực hiện một vài tương tác giữa các thành phần thông qua Http request hoặc những message asynchronous khác v.v... Tính hợp lệ của các tương tác này có thể được kiểm tra bằng cách kiểm tra các kết quả đầu ra cụ thể.
Tuy nhiên cách làm này có rất nhiều nhược điểm mặc dù hầu hết các công ty vẫn tin rằng E2E Testing là cách tốt nhất để phát hiện lỗi, tuy nhiên lại khiến cho quá trình delivery diễn ra càng ngày càng chậm.
- Những thay đổi manually trên staging gây ảnh hưởng tới test data và việc phải maintain để đảm bảo môi trường clean trở thành 1 vấn đề.
- Chậm trễ trong việc delivery.
- Ít bug được phát hiện trên staging. Một thử nghiệm cho thấy với hơn 1000 lần chạy, chỉ có 42 lần chạy thất bại và 1 bug được phát hiện.
- Kém hiệu quả, bug vẫn thường xuyên được tìm thấy trên production.
Vậy nếu điều này tiếp tục diễn ra, chúng ta sẽ mất nhiều thời gian hơn trong quá trình CI/CD. Mọi người sẽ thực hiện các đợt commit với nhiều thay đổi hơn và mất nhiều thời gian hơn để triển khai, đồng thời vẫn có thể xảy ra lỗi trên production. Tình huống tương tự cũng xảy ra tại nhiều công ty khác trong quá trình thực hiện E2E Test.
Từ đó tại Nubank đã sử dụng Consumer Driven Contract (CDC) testing để thay thế E2E Test. CDC Testing cho phép mô tả sự tương tác giữa các dịch vụ thông qua những kỳ vọng input/output mà chúng đáp ứng. CDC cho phép các team có thể hoạt động một cách độc lập với nhau, đòi hỏi ít sự phối hợp cũng như cơ sở hạ tầng hơn.
👨💻Góc lập trình
(by ndaadn and phucnh)
Đề ra tuần này: Split Array Largest Sum
Cho một mảng số nguyên không âm nums và một số nguyên dương k, hãy chia mảng nums thành k mảng con (không rỗng) sao cho ta thu được những mảng con với tổng lớn nhất trong số các mảng con là nhỏ nhất. Hãy trả lại tổng lớn nhất mà ta có thể thu được.
Ví dụ:
Input: nums = [7,2,5,10,8], k = 2
Output: 18
Giải thích: Ta có 4 cách để chia mảng nums thành 2 mảng con như sau:
Cách 1, ta có [7] và [2,5,10,8], với tổng lớn nhất trong số các mảng con là 25.
Cách 2, ta có [7,2] và [5,10,8], với tổng lớn nhất trong số các mảng con là 23.
Cách 3, ta có [7,2,5] và [10,8], với tổng lớn nhất trong số các mảng con là 18.
Cách 4, ta có [7,2,5,10] và [8], với tổng lớn nhất trong số các mảng con là 24.
Như vậy, cách chia tốt nhất là chia thành hai mảng con [7,2,5] và [10,8], với tổng lớn nhất là 18.
Ứng dụng của thuật toán này?
Hãy tưởng tượng bạn đang quản lý một đội xe giao hàng có nTrucks chiếc xe cho một công ty logistics. Bạn có một danh sách các đơn đặt hàng được biểu thị dưới dạng một mảng số nguyên orderWeights, trong đó mỗi phần tử đại diện cho trọng lượng của một đơn đặt hàng tính bằng kilogram. Mục tiêu của bạn là chia các đơn hàng này cho các xe trong đội giao hàng, sao cho trọng lượng tối đa mà bất kỳ xe giao hàng nào mang là tối thiểu. Trong tình huống này:
orderWeights tương ứng với trọng lượng của các đơn đặt hàng khác nhau cần được giao hàng.
nTrucks là số lượng xe bạn có trong đội giao hàng.
Nhiệm vụ của bạn là tìm cách phân công đơn đặt hàng vào các lộ trình một cách tối ưu, đảm bảo rằng không có xe nào bị quá tải và trọng lượng được mang bởi xe nặng nhất là thấp nhất có thể. Trọng lượng tối đa được giảm xuống trên bất kỳ xe nào đại diện cho hiệu suất của hoạt động giao hàng của bạn.
Lời giải tuần trước: Minimum Number of People to Teach
Do đề bài chỉ cho phép ta dạy một ngôn ngữ, nên ta có thể tìm ngôn ngữ thoả mãn điều kiện đề bài bằng cách thử dạy từng ngôn ngữ rồi chọn ngôn ngữ cần ít số người học nhất. Ta thực hiện giải thuật trên theo các bước như sau:
Tìm những cặp không thể giao tiếp với nhau
Thử dạy từng ngôn ngữ cho các cặp không thể giao tiếp với nhau để tìm ra số người học nhỏ nhất
Giải thuật được thực hiện như sau:
class Solution {
public int minimumTeachings(int n, int[][] languages, int[][] friendships) {
// map of user and speakable languages
Map<Integer, Set<Integer>> userLanguages = new HashMap<>();
for (int i = 0; i < languages.length; i++) {
userLanguages.put(i + 1, new HashSet<>());
for (int l : languages[i]) {
userLanguages.get(i + 1).add(l);
}
}
// find the friendships w/o common language
boolean[] canCommunicate = new boolean[friendships.length];
for (int l = 1; l <= n; l++) {
for (int i = 0; i < friendships.length; i++) {
if (userLanguages.get(friendships[i][0]).contains(l) &&
userLanguages.get(friendships[i][1]).contains(l)) {
canCommunicate[i] = true;
}
}
}
// find language that can be taught to min users
int ans = 500; // maximum of number of users is 500
for (int l = 1; l <= n; l++) {
Set<Integer> countUsersToTeach = new HashSet<>();
for (int i = 0; i < friendships.length; i++) {
int u1 = friendships[i][0];
int u2 = friendships[i][1];
if (canCommunicate[i]) {
continue;
}
if (!userLanguages.get(u1).contains(l)) {
countUsersToTeach.add(u1);
}
if (!userLanguages.get(u2).contains(l)) {
countUsersToTeach.add(u2);
}
}
ans = Math.min(ans, countUsersToTeach.size());
}
return ans;
}
}
Độ phức tạp về thời gian (time complexity) của giải thuật là O(m*n), trong đó m là số người, n là số ngôn ngữ.
Ngoài cách tiếp cận trên, ta cũng có thể tìm ngôn ngữ thoả mãn điều kiện đề bài như sau:
Tìm những cặp không thể giao tiếp được với nhau
Tìm ngôn ngữ được nhiều người biết nhất, và dạy lại cho những người còn lại
Ngoài ra, còn một cách giải khác dùng binary search. Xin dành lại cho các bạn đọc cùng khám phá.
💭Góc bạn đọc- Một tuần làm việc của EM (p4)
Thứ năm - phỏng vấn và high-level org coordination
Dạo gần đây hay có phỏng vấn để mở rộng team. Bản thân mình sau gần 1 năm không tuyển người cũng bắt đầu làm quen lại với các quy trình từ viết JD, đăng tuyển, lọc CV, phỏng vấn, offer, … và phát hiện ra sau gần 1 năm quan điểm cũng ít nhiều thay đổi về quy trình này.
Viết JD. Sau một thời gian dài chỉ dùng những mẫu JD trên mạng hoặc viết những câu chung chung, mình bắt đầu phát hiện ra là để viết JD được tốt thì bản thân người manager phải thực sự hiểu nhu cầu của mình. Việc viết JD chi tiết và thực tế sẽ giúp cho ứng viên tự xác định bản thân có phù hợp không, hoặc các bạn talent acquisition, headhunter có thể dựa vào đó để sàng lọc người phù hợp. Chi tiết ở đây là cần mô tả:
Giới thiệu tổng quan ngắn gọn về dự án và team đang tuyển
Tổng quan về vai trò đang đăng tuyển
Trách nhiệm cụ thể của vai trò này
Yêu cầu
Kỹ năng mềm
Kinh nghiệm ở vị trí liên quan
Học vấn
Phỏng vấn. Khi đã hiểu nhu cầu của mình thì việc phỏng vấn cũng cần được sắp xếp dựa theo nhu cầu thực tế. Có một cuộc tranh luận lâu đời trong ngành là phỏng vấn developer/engineer thì có cần phỏng vấn thuật toán sâu hoặc hỏi xoáy đáp xoay kiểu “Google” hay không? Phỏng vấn thì sẽ cần bao nhiêu vòng là đủ, …
Khó có thể nói đâu là cách tốt nhất. Tuy nhiên gần đây team mình cũng bắt đầu bỏ các bài phỏng vấn theo hướng competitive programming, hoặc phỏng vấn những thứ sẽ không thực sự được dùng trong công việc hằng ngày ở công ty. Suy cho cùng, phỏng vấn là để tuyển người vào làm những công việc hàng ngày, nếu quá trình phỏng vấn tập trung quá nhiều vào competitive programming hoặc hỏi những thứ mà công việc hàng ngày không cần thì thứ nhất là người tuyển chưa chắc đã phù hợp mà có khi lại vượt quá yêu cầu, thứ hai là người phỏng vấn đậu sẽ có “expectation” sai về công việc họ phải làm hằng ngày. Phỏng vấn quá khó hoặc cao siêu mà công việc hàng ngày không cần có thể gây mất tinh thần về lâu về dài.
Offer. Phỏng vấn xong rồi, offer ai cũng là một vấn đề. Những câu hỏi cần phải trả lời khi chọn người để offer cũng như mức offer có thể bao gồm:
Phỏng vấn đậu là offer ngay? Tùy vào tình hình thị trường và lượng ứng viên cũng như nhu cầu thực tế mà người manager có thể chọn offer ngay khi gặp ứng viên phù hợp hay sẽ chờ các ứng viên trong cùng batch phỏng vấn được phỏng vấn hết.
Offer nên ở mức nào? Các công ty lớn thường sẽ có range lương và có policy về việc tăng lương định kỳ. Nhưng sẽ hiếm khi bạn offer ở mức tối đa ở range lương vì nếu làm vậy sẽ khó tăng lương định kỳ cho ứng viên nên thường mức offer sẽ ở mức vừa phải.
Ứng viên này sẽ đóng góp cho team như thế nào? Tuỳ vào tình hình cụ thể của team mà có khi người manager sẽ cần người năng nổ để giao tiếp, hoặc người thiên về hạ tầng để xử lý các tasks hạ tầng, hoặc người có chuyên môn về AI để lái định hướng của team sang hướng AI, hoặc có khi cần một bạn trẻ nhưng năng nổ và học hỏi nhanh để đẩy nhanh tốc độ thử nghiệm công nghệ mới, …
Kinh nghiệm dành cho các bạn ứng viên:
Project, team, quản lý của bạn rất quan trọng, đặc biệt là trong môi trường công ty lớn nơi có nhiều team và nhiều projects khác nhau. Hãy tìm hiểu về project bạn sẽ làm vì trong môi trường quy mô lớn, việc đổi project sẽ không dễ. Hãy hỏi những câu hỏi cụ thể như stack công nghệ là gì, bài toán hoặc project mà bạn đang phỏng vấn là gì, có những challenge gì, …
Hãy đặt câu hỏi khôn ngoan để lựa chọn môi trường phù hợp. Phỏng vấn là một quá trình hai chiều trong đó công ty tìm người phù hợp và ở chiều ngược lại bạn cũng muốn tìm môi trường phù hợp cho mình. Hãy hỏi những câu hỏi dạng STAR với những tình huống cụ thể cho người phỏng vấn để khai thác thông tin tốt hơn. Ví dụ như:
Đừng hỏi: anh/chị có thể chia sẻ thêm về văn hoá công ty không?
Hãy hỏi: công ty có OT nhiều không? Công ty có những loại hình training nào? Một ngày làm việc điển hình của một bạn có vai trò tương tự trong team anh/chị?
Quan trọng là hợp tính. Bạn không đậu phỏng vấn team này chưa chắc đã là do bạn kém mà có khi là do không hợp với team hoặc không hợp thời điểm, bạn vẫn có thể thử đề xuất phỏng vấn với team khác.
Các loại benefit ngoài lương như thưởng, stock, … cũng rất quan trọng. Khi thương lượng nên cân nhắc tổng thu nhập năm thay vì chỉ ưu tiên lương cứng. Một số công ty có thể offer lương cứng thấp nhưng bù lại tổng thu nhập năm lại cao do các phần khác như stock và bonus nhiều. Có một số công ty thì ngược lại.
📜History
(by lpv)
Vào ngày 25/8/1991, Linus đã giới thiệu trong một group rằng ông đang xây dựng một hệ điều hành mở mà sau này đã được biết đến với cái tên Linux.
Hello everybody out there using minix -
I'm doing a (free) operating system (just a hobby, won't be big and
professional like gnu) for 386(486) AT clones. This has been brewing
since april, and is starting to get ready. I'd like any feedback on
things people like/dislike in minix, as my OS resembles it somewhat
(same physical layout of the file-system (due to practical reasons)
among other things).I've currently ported bash(1.08) and gcc(1.40), and things seem to work.
This implies that I'll get something practical within a few months, and
I'd like to know what features most people would want. Any suggestions
are welcome, but I won't promise I'll implement them :-)Linus (torv...@kruuna.helsinki.fi)
PS. Yes - it's free of any minix code, and it has a multi-threaded fs.
It is NOT protable (uses 386 task switching etc), and it probably never
will support anything other than AT-harddisks, as that's all I have :-(.
🛠️Code & Tools
Novu: The open-source notification infrastructure with fully functional embedded notification center.
Walk: Walk is a Terminal file manager with preview mode, icons support, and image preview.
Python Debugging Cheat Sheet
💭Quotes
Coding like poetry should be short and concise. ― Santosh Kalwar
Bài này trúng lúc đang làm migration monolithic to microservice luôn. Cảm ơn BBT.
Chưa có điều kiện để thử qua giải pháp khác, tuy nhiên mình đánh giá End-to-End Test Suite khá phù hợp cho những ứng dụng cần nhiều nhiều vụ phức tạp kiểu enterprise. Ví dụ về việc tính tiền dịch vụ theo kiểu subscription và phát hành hóa đơn với nhiều khuyến mãi bao gồm voucher, prepaid... thì việc test bằng dữ liệu mô phỏng như các trường hợp thực tế rất cần thiết.