Thư xác nhận là phần trong luồng đăng ký mà một bài kiểm thử trình duyệt không thể tự mình đi hết. Phải có thứ gì đó sở hữu một địa chỉ, nhận thư và trả mã về cho bài kiểm thử. API hộp thư tạm thời làm đúng việc đó: bộ kiểm thử nhờ một dịch vụ tạo hộp qua HTTP, đọc thư đến, và vứt bỏ hộp khi ca kiểm thử xong. Không trình duyệt, không hộp thư dùng chung giữa người với người, và không sao chép thủ công.
Bài này bàn về phía API của cách sắp đặt đó. Đây không phải chuyện trỏ ứng dụng vào một điểm nhận nội bộ; đó là cách bắt thư trong CI, và hai việc giải quyết hai vấn đề khác nhau. Bắt cục bộ chứng minh ứng dụng của bạn gửi đi cái gì. API hộp thư chứng minh cái gì thật sự đến, qua một đường gửi thật, tại địa chỉ do bài kiểm thử nắm giữ.
Vì sao dùng API hộp thư trong kiểm thử?
Vì lựa chọn còn lại hoặc là hộp thư của người thật, hoặc không có gì.
Hộp thư dùng chung là một fixture tồi. Nhiều lượt chạy đọc cùng một hộp, thư từ lượt trước vẫn còn nằm đó, và địa chỉ tích tụ lưu lượng mà không bài kiểm thử nào yêu cầu. Mỗi khẳng định rồi phải đoán thư nào thuộc ca hiện tại, và chính sự đoán mò ấy sinh ra chập chờn.
Thu hoạch giao diện web của nhà cung cấp bằng trình duyệt là lựa chọn tồi thứ hai. Nó khiến bài kiểm thử phụ thuộc vào đánh dấu đổi không báo trước, vào trạng thái phiên, và vào một lần đăng nhập mà bộ kiểm thử phải trông nom. Khoảnh khắc nhà cung cấp đổi kiểu dáng một nút, bộ kiểm thử xanh bỗng đỏ vì lý do không liên quan gì đến sản phẩm.
API hộp thư xóa cả hai vấn đề. Địa chỉ được tạo cho ca kiểm thử, rỗng theo cấu trúc, và được đọc qua một giao diện ổn định mà bài kiểm thử gọi trực tiếp được. Bộ kiểm thử không còn bận tâm nhà cung cấp trông thế nào, chỉ quan tâm hợp đồng còn giữ: tạo, nhận, đọc, xóa.
Còn một lý do về quyền riêng tư. Một địa chỉ tạo qua API không đại diện cho ai cả. Nó không phải hộp thư của một người, không phải nơi một lá thư thật có thể rơi vào, và nó bị vứt đi cùng lượt chạy.
Một bài kiểm thử thật sự cần những endpoint nào?
API hộp thư có thể phơi ra hàng chục tuyến, nhưng client kiểm thử chỉ cần bốn thao tác, và gọi tên chúng theo cách bộ kiểm thử dùng sẽ hữu ích.
Tạo trả về một địa chỉ và một handle. Địa chỉ là thứ được nói cho ứng dụng đang kiểm thử làm nơi nhận. Handle, thường là token hay mã định danh, là thứ bài kiểm thử dùng để hỏi về hộp đó trong mọi lần gọi sau. Bộ kiểm thử nên coi cặp này là một đối tượng và đừng bao giờ dựng lại handle từ địa chỉ, vì nhà cung cấp được tự do khiến hai thứ không liên quan.
Liệt kê trả về tóm tắt chứ không trả nội dung: mỗi thư một mục, kèm mã định danh, người gửi, tiêu đề và thời điểm đến. Đây là lời gọi mà vòng thăm dò nên dùng, vì nó rẻ và đủ để trả lời câu hỏi duy nhất quan trọng lúc đầu: đã có gì đến chưa.
Đọc trả về một thư trọn vẹn, gồm cả phần văn bản và HTML. Mã nằm ở đây, và đây là lời gọi chỉ nên thực hiện sau khi liệt kê đã báo một kết quả khớp.
Dọn xóa thư khỏi hộp hoặc xóa cả hộp. Bài kiểm thử cần nó vì hai lý do: đặt lại giữa các lần thử mà không tạo địa chỉ mới, và dọn dẹp khi ca kết thúc.
Một số dịch vụ thêm endpoint chờ hoặc thăm dò dài, giữ kết nối cho tới khi thư đến hoặc hết thời gian. Nó tiện, nhưng client vẫn nên lùi về liệt kê được, vì lời gọi chờ là phần dễ bị giới hạn tốc độ nhất.
Làm sao thăm dò mã mà không chập chờn?
Lỗi phổ biến nhất trong loại kiểm thử này là chờ cố định. Một số giây cố định là phỏng đoán: quá ngắn khi thư đến chậm, phí hoài khi thư đến nhanh, và sai cả hai hướng trên một máy CI đang tải. Thay nó bằng một vòng gọi liệt kê, kiểm tra khớp, và trả về ngay khi tìm thấy, với một trần khiến bài kiểm thử thất bại thay vì treo job.
Khớp là nửa còn lại của vấn đề. Thư mà bài kiểm thử muốn là thư gửi tới địa chỉ ca kiểm thử đã tạo và, nếu hộp có thể chứa nhiều loại thư, là thư có tiêu đề mang một mảnh ổn định. Chọn kết quả khớp mới nhất, để một lần gửi lặp do thử lại không làm rối việc đọc. Đừng bao giờ lấy thư đầu tiên vô điều kiện; trên một địa chỉ dùng lại, đó đúng là cách một mã cũ bị đem ra xác minh.
Trích xuất cần có điểm neo. Nội dung có thể chứa số tham chiếu, dấu thời gian và giá, và một bộ phân tích vơ lấy chuỗi chữ số đầu tiên đôi khi vơ nhầm một trong số đó thay vì mã. Tìm câu dẫn vào mã, đọc mã quanh nó, và khi không khớp gì thì cho thất bại kèm nguyên nội dung.
Cuối cùng, tôn trọng giới hạn gửi lại. Luồng mã thường chỉ cho gửi vài lần trong một cửa sổ ngắn, và giới hạn ấy là một phần hành vi đang được kiểm. Một bài kiểm thử cứ bấm nút lần nữa để lấy mã mới rồi sẽ bị từ chối và thất bại vì lý do sai. Hãy thử lại bằng cách đọc hộp một lần nữa, không phải bằng cách kích hoạt thêm một thư.
Làm sao nối vào bộ kiểm thử đầu-cuối hay CI?
Hình dạng sạch sẽ là một fixture. Trước khi luồng bắt đầu, fixture tạo một hộp và trả về địa chỉ. Bài kiểm thử điều khiển ứng dụng bằng địa chỉ đó. Sau khi ứng dụng xác nhận đã gửi gì đó, khẳng định đọc hộp và trích mã. Khi ca kết thúc, fixture xóa hộp.
Giữ client nhỏ và có thể tiêm. Một mô-đun bọc bốn lời gọi; bài kiểm thử phụ thuộc mô-đun đó, chứ không phải HTTP thô rải khắp bộ kiểm thử. Điều này cho phép thay bằng bản giả trong kiểm thử đơn vị và trỏ cùng bộ kiểm thử sang nhà cung cấp khác mà không viết lại khẳng định.
Trong CI, thông tin xác thực nằm trong kho bí mật của job, không bao giờ trong kho mã và không bao giờ trong một dòng log. Cho mỗi job hoặc mỗi worker song song hộp riêng, và thêm tiền tố nhận diện lượt chạy vào địa chỉ sinh ra, để một thư lạc có thể được quy cho bằng quan sát. Đặt thời gian chờ của client thấp hơn thời gian chờ của chính job, để một vòng thăm dò kẹt sẽ thất bại với thông báo rõ ràng thay vì bị hủy job đột ngột.
Thử lại việc đọc, không thử lại cả luồng. Nếu mã chưa đến, chờ rồi đọc lại; chạy lại đăng ký sẽ sinh thêm một thư và, cùng với nó, một ứng viên thứ hai cho khẳng định. Và giữ API hộp thư ngoài các luồng sản xuất: nó là hạ tầng kiểm thử, và bộ kiểm thử không bao giờ được có khả năng gửi tới khách hàng thật từ nó.
Luồng quanh mã, chứ không phải cơ chế đọc mã, được bàn trong kiểm thử luồng xác minh thư, còn bước phân tích cú pháp được trình bày riêng trong OTP trong kiểm thử đầu-cuối.
Cô lập và dọn dẹp
Mỗi ca một địa chỉ là quy tắc ngăn phần lớn thất bại giữa các bài kiểm thử. Nó bỏ đi nhu cầu suy đoán thư nào thuộc về ai và khiến câu hỏi về độ mới biến mất, vì hộp thư chưa từng nhận gì ngoài lưu lượng của một ca.
Dọn dẹp phải tường minh và vô điều kiện. Xóa hộp trong một bước teardown chạy dù ca đậu hay rớt, chứ không chỉ trên đường hanh thông. Chỉ dựa vào thời gian sống của nhà cung cấp là một sai lầm: thư có thể nán lại đủ lâu để một lượt chạy sau trên cùng máy đọc được, và thời gian sống ấy là tiện lợi, không phải bảo đảm.
Nếu dọn dẹp thất bại, ghi lại rồi để bộ kiểm thử chạy hết. Lỗi dọn dẹp đáng để biết, nhưng không giống khiếm khuyết sản phẩm, và làm hỏng lượt chạy vì nó sẽ dạy đội ngũ coi nhẹ thất bại ở bước teardown. Hãy xử lý mọi thứ địa chỉ đã nhận như dữ liệu kiểm thử: nó tồn tại cho một khẳng định, không nên xuất ra hay chia sẻ, và không bao giờ được coi là đầu mối liên hệ của bất kỳ ai.
Giới hạn và lưu ý
API hộp thư vẫn là một phụ thuộc bên thứ ba, và giới hạn của nó thành giới hạn của bạn. Giới hạn mỗi phút có thể từ chối một loạt lệnh tạo từ lượt chạy song song lớn. Hạn mức khống chế số địa chỉ tồn tại cùng lúc. Thư có thể đến trễ, và một thư đến trễ trông y hệt thư mất tích cho tới khi nó tới.
Tên miền dùng một lần cũng bị chặn rộng khắp. Tên miền của nhà cung cấp có thể bị chính biểu mẫu đăng ký bạn đang kiểm từ chối, biến một bài kiểm thử hợp lệ thành thất bại khó hiểu. Khi điều đó xảy ra, câu trả lời không phải là mở ngoại lệ cho nhà cung cấp, mà là hiểu xem sản phẩm đang kiểm có cố ý từ chối địa chỉ dùng một lần không, rồi chủ động kiểm chính hành vi đó.
Tóm lại cho trung thực: API hộp thư là công cụ đúng để khẳng định cái gì đến. Để khẳng định cái gì ứng dụng của bạn phát ra, một điểm nhận cục bộ nhanh hơn và không có hạn mức. Phần lớn bộ kiểm thử trưởng thành dùng cả hai: bắt cục bộ cho phần lớn khẳng định, và API hộp thư chỉ khi chính đường gửi thật là đối tượng kiểm thử.
Bước tiếp theo
Tìm một bài kiểm thử đọc mã bằng cách thăm dò hộp dùng chung và thay nó bằng một fixture tạo địa chỉ mới từ API hộp thư. Ghi địa chỉ vào log cùng lượt chạy, xóa nó trong teardown, và xem bao nhiêu phần chập chờn bạn từng chịu đựng tự nhiên biến mất. Khi cần một hộp thư thật bằng tay, trang thư tạm thời tạo ngay một cái, và những địa chỉ nó đưa ra là giàn giáo cho một lượt chạy, không bao giờ là danh tính thật.