Là kỹ sư, chúng tôi muốn xây dựng những thứ hoạt động được nhưng với mỗi tính năng mới mà chúng tôi tạo ra, chúng tôi chắc chắn sẽ tăng quy mô và độ phức tạp của ứng dụng của mình.
Khi sản phẩm phát triển, việc kiểm tra thủ công (ví dụ: bằng tay) mọi chức năng bị ảnh hưởng bởi những thay đổi của bạn sẽ ngày càng tốn nhiều thời gian hơn.
Việc thiếu các thử nghiệm tự động dẫn đến việc chúng tôi mất quá nhiều thời gian và làm chậm tốc độ vận chuyển hoặc chi tiêu quá ít để tiết kiệm vận tốc, dẫn đến các lỗi mới tồn đọng cùng với các cuộc gọi đêm khuya từ PagerDuty.
Ngược lại, máy tính có thể được lập trình để làm điều tương tự nhiều lần . Vì vậy, hãy giao việc kiểm tra cho máy tính!
Ý tưởng kim tự tháp Thử nghiệm gợi ý ba loại thử nghiệm chính: đơn vị, tích hợp và từ đầu đến cuối . Hãy đi sâu vào từng loại và hiểu lý do tại sao chúng ta cần từng loại.
Đơn vị là một phần logic nhỏ mà bạn kiểm tra một cách riêng biệt (không dựa vào các thành phần khác).
Kiểm tra đơn vị là nhanh chóng. Họ hoàn thành trong vòng vài giây. Sự cô lập cho phép họ chạy chúng bất kỳ lúc nào, cục bộ và trên CI mà không cần khởi động các dịch vụ phụ thuộc/thực hiện lệnh gọi API và cơ sở dữ liệu.
Ví dụ về kiểm thử đơn vị: Một hàm chấp nhận hai số và tính tổng chúng lại với nhau. Chúng tôi muốn gọi nó bằng các đối số khác nhau và khẳng định rằng giá trị trả về là chính xác.
// Function "sum" is the unit const sum = (x, y) => x + y test('sums numbers', () => { // Call the function, record the result const result = sum(1, 2); // Assert the result expect(result).toBe(3) }) test('sums numbers', () => { // Call the function, record the result const result = sum(5, 10); // Assert the result expect(result).toBe(15) })
Một ví dụ thú vị hơn là thành phần React hiển thị một số văn bản sau khi yêu cầu API kết thúc. Chúng tôi cần mô phỏng mô-đun API để trả về các giá trị cần thiết cho các thử nghiệm của mình, hiển thị thành phần và xác nhận HTML được hiển thị có nội dung chúng tôi cần.
// "MyComponent" is the unit const MyComponent = () => { const { isLoading } = apiModule.useSomeApiCall(); return isLoading ? <div>Loading...</div> : <div>Hello world</div> } test('renders loading spinner when loading', () => { // Mocking the API module, so that it returns the value we need jest.mock(apiModule).mockReturnValue(() => ({ useSomeApiCall: jest.fn(() => ({ // Return "isLoading: false" for this test case isLoading: false })) })) // Execute the unit (render the component) const result = render(<MyComponent />) // Assert the result result.findByText('Loading...').toBeInTheDocument() }) test('renders text content when not loading', () => { // Mocking the API module jest.mock(apiModule).mockReturnValue(() => ({ useSomeApiCall: jest.fn(() => ({ // Return "isLoading: false" for this test case isLoading: false })) })) // Execute the unit (render the component) const result = render(<MyComponent />) // Assert the result result.findByText('Hello world').toBeInTheDocument() })
Khi đơn vị của bạn tương tác với các đơn vị khác (phụ thuộc) , chúng tôi gọi đó là sự tích hợp . Các thử nghiệm này chậm hơn thử nghiệm đơn vị nhưng chúng kiểm tra cách các phần trong ứng dụng của bạn kết nối.
Ví dụ về kiểm thử tích hợp: Một dịch vụ tạo người dùng trong cơ sở dữ liệu. Điều này đòi hỏi phải có phiên bản DB ( phụ thuộc ) khi thực hiện kiểm thử. Chúng tôi sẽ kiểm tra xem dịch vụ có thể tạo và truy xuất người dùng từ DB hay không.
import db from 'db' // We will be testing "createUser" and "getUser" const createUser = name => db.createUser(name) // creates a user const getUser = name => db.getUserOrNull(name) // retrieves a user or null test("creates and retrieves users", () => { // Try to get a user that doesn't exist, assert Null is returned const nonExistingUser = getUser("i don't exist") expect(nonExistingUser).toBe(null); // Create a user const userName = "test-user" createUser(userName); // Get the user that was just created, assert it's not Null const user = getUser(userName); expect(user).to.not.be(null) })
Đây là thử nghiệm toàn diện khi chúng tôi thử nghiệm ứng dụng được triển khai đầy đủ , trong đó tất cả các phần phụ thuộc của nó đều có sẵn. Những thử nghiệm đó mô phỏng tốt nhất hành vi thực tế của người dùng và cho phép bạn nắm bắt tất cả các vấn đề có thể xảy ra trong ứng dụng của mình, nhưng chúng là loại thử nghiệm chậm nhất .
Bất cứ khi nào muốn chạy thử nghiệm toàn diện, bạn phải cung cấp tất cả cơ sở hạ tầng và đảm bảo có sẵn các nhà cung cấp bên thứ 3 trong môi trường của bạn.
Bạn chỉ muốn có chúng cho các tính năng quan trọng của ứng dụng.
Chúng ta hãy xem một ví dụ thử nghiệm toàn diện: Luồng đăng nhập. Chúng tôi muốn truy cập ứng dụng, điền thông tin đăng nhập, gửi ứng dụng và xem thông báo chào mừng.
test('user can log in', () => { // Visit the login page page.goto('https://example.com/login'); // Fill in the login form page.fill('#username', 'john'); page.fill('#password', 'some-password'); // Click the login button page.click('#login-button'); // Assert the welcome message is visible page.assertTextVisible('Welcome, John!') })
Hãy nhớ rằng kiểm thử toàn diện chậm hơn kiểm thử tích hợp và kiểm thử tích hợp chậm hơn kiểm thử đơn vị .
Nếu tính năng bạn đang phát triển có vai trò quan trọng, hãy cân nhắc viết ít nhất một bài kiểm tra toàn diện (chẳng hạn như kiểm tra cách hoạt động của chức năng Đăng nhập khi phát triển quy trình Xác thực).
Bên cạnh các luồng quan trọng của nhiệm vụ, chúng tôi muốn thử nghiệm càng nhiều trường hợp đặc biệt và các trạng thái khác nhau của tính năng càng tốt. Kiểm tra tích hợp cho phép chúng tôi kiểm tra cách các phần của ứng dụng hoạt động cùng nhau.
Có các bài kiểm tra tích hợp cho các điểm cuối và các thành phần máy khách là một ý tưởng hay. Điểm cuối phải thực hiện các thao tác, tạo ra kết quả mong đợi và không đưa ra bất kỳ lỗi không mong muốn nào.
Các thành phần máy khách phải hiển thị nội dung chính xác và phản hồi các tương tác của người dùng theo cách bạn mong đợi họ phản hồi.
Và cuối cùng, khi nào chúng ta nên chọn unit test ? Tất cả các hàm nhỏ có thể được kiểm tra riêng biệt, chẳng hạn như sum
tổng các số, Button
hiển thị thẻ <button>
, đều là những ứng cử viên tuyệt vời cho các bài kiểm tra đơn vị. Các đơn vị sẽ hoàn hảo nếu bạn tuân theo phương pháp Phát triển dựa trên thử nghiệm .
Viết một số bài kiểm tra! (nhưng bắt đầu nhỏ)
Làm những điều trên một lần để hiểu nó hoạt động như thế nào. Sau đó, thực hiện lại trong quá trình xử lý một số tính năng/lỗi. Sau đó chia sẻ nó với đồng nghiệp của bạn để tất cả các bạn viết bài kiểm tra, tiết kiệm thời gian và ngủ ngon hơn vào ban đêm!