Unit test

- 6 mins

Kiểm thử là cách kiểm tra chương trình còn bug nào không hoặc tìm ra những điểm hiệu năng kém để tối ưu. Không phải chỉ tester, dev sau khi viết code xong cũng cần biết cách kiểm thử, viết test-case để kiểm soát được các lỗi trong code và tối ưu. Thông thường có 2 cách tiếp cận để testing:

Để kiểm tra từng phần bên trong mỗi chương trình khi thực hiện white-box testing, có nhiều mức độ thực hiện bao gồm:

Ở đây ta sẽ tập trung nói về unit testing. Unit testing sẽ thực hiện kiểm tra từng unit trong chương trình (method, class,…) đã hoạt động đúng yêu cầu hay chưa. Tại sao phải cần unit testing? Trong quá trình code, khi cần phát triển nhanh, dev có thể viết từ đầu đến cuối chương trình sau đó test một vài trường hợp thấy hoạt động đúng là coi như đã hoàn thành. Tuy nhiên có nhiều trường hợp code không thể cover hết các trường hợp có thể xảy ra, khi đó sẽ phát sinh lỗi. Ngoài ra khi code nhanh để release tính năng, nhiều đoạn code có thể bị chậm mà khi chạy trên môi trường product mới phát hiện ra. Đây là khi unit có thể được sử dụng để fix bug hoặc tối ưu một đoạn code nào đó trong chương trình.

Ngược lại, việc bỏ thời gian viết unit test cũng sẽ tốn thêm thời gian làm chậm quá trình code release sản phẩm. Nhưng việc viết unit test này nhằm đảm bảo giảm thiểu lỗi, có thể kiểm soát được các khả năng thể xảy ra khi chạy chương trình đặc biệt là với các tính năng sau này, dễ maintain và improve hơn.

Để viết unit test hiệu quả, ta có thể tham khảo nguyên tắc sau: https://martinfowler.com/bliki/GivenWhenThen.html trong đó:

Unit test with java

Để viết unit test trong java, ta có thể sử dụng framework Junit. Để sử dụng được cần bổ sung thêm thư viện sau vào trong project:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

Hiện nay đối với các IDE thì Junit được tích hợp sẵn vào bên trong IDE rồi nên không cần thêm thư viện trên vào nữa.

Ví dụ ta có đoạn code sau:

public class MathUtil {
 
    private MathUtil() {
    }
 
    public static int saltKey(int dividend, int divisor) {
        if (divisor == 0) {
            throw new IllegalArgumentException("Cannot divide by zero (0).");
        }
        return dividend % divisor;
    }
 
}

Trong method saltKey tạo ra với mục đích tạo salt key cho các user id đầu vào sử dụng làm row key để lưu trữ trong các DB ví dụ như HBase. Để kiểm tra method này hoạt động như thế nào, ta cần kiểm tra trường hợp chia cho 0, chia cho các số khác xem phân bố kết quả thu được như thế nào. Test case của class này được viết như sau:

public class MathUtilTest {
 
    @Test
    public void buildSaltKey() {
        int trueSalt = 1;  // expected result
        int saltKey = MathUtil.saltKey(7, 2);
        Assert.assertEquals(trueSalt, actual);
    }
 
}

Ở trên ta kiểm tra trường hợp build salt key xem kết quả tạo ra của method có đúng với kết quả ta cần không. Một ví dụ khác để kiểm tra phân phối của key, ta có thể truyền vào một dãy các user id từ ngoài vào để kiểm tra salt key thu được có đáp ứng yêu cầu hay không.

Unit test with python

Để viết unit test trong python ta có nhiều thư viện có thể sử dụng và được tích hợp sẵn bên trong python. Ở đây ta có thể sử dụng pytest hoặc unittest. Trong ví dụ sau là các sử dụng unittest:

class MathUtils:

    def __init__(self):
        ...

    @staticmethod
    def salt_key(dividend: int, divisor: int):
        return dividend % divisor

Bây giờ ta viết file test, nếu kết quả không đúng sẽ in ra màn hình Failed!

import unittest


class TestSaltKey(unittest.TestCase):

    def runTest(self):
        self.assertEqual(MathUtils.salt_key(2, 3), 2, "Failed!")

Sau khi chạy file test kết quả thông báo thành công trên màn hình như sau:

Ran 1 test in 0.004s

OK
Launching unittests with arguments python -m unittest

hoặc có lỗi nếu sửa expected = 4:

Ran 1 test in 0.007s

FAILED (failures=1)

Failed!
4 != 2

Expected :2
Actual   :4
<Click to see difference>

Trên đây chỉ là các cách đơn giản để viết unittest trong java hoặc python để có thể áp dụng được vào các trường hợp hay gặp trong thực tế. Ngoài ra, khi thực hiện test với class, method phức tạp hơn, có nhiều phụ thuộc repository, object khác thì sẽ cần sử dụng đến các chức năng khác của framework hỗ trợ để tạo các object giả (mock) giúp code có thể test được.

Tài liệu tham khảo:

comments powered by Disqus
rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora