Thursday, 12 October 2017

[Python] unittest với assertTrue

Đây không phải một bài viết dài giải thích test là gì, unittest là gì.

Python unittest

Khi sử dụng thư viện unittest của Python, ta thường dễ bị cuốn hút bởi method assertTrue, thường viết các method như sau:

self.assertTrue(7 in thatlist)
self.assertTrue(isinstance(res, list))
self.assertTrue(res > 0)
self.assertTrue(res == [1,2,3,4])

Code vẫn chạy và test bình thường, nhưng nếu test fail, output sẽ rất khó hiểu:


Code gõ trên IPython, với Python 3.5

In [1]: import unittest
In [2]: class TestFoo(unittest.TestCase):
   ...:     def test_true(self):
   ...:         x = 1
   ...:         self.assertTrue(5 > x)
   ...:     def test_false(self):
   ...:         x = 7
   ...:         self.assertTrue(5 > x)
   ...:       
In [3]: unittest.main()
F.
======================================================================
FAIL: test_false (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-2-0bc11da92fb6>", line 7, in test_false
    self.assertTrue(5 > x)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (failures=1)

Test test_false đã failed, với nội dung
 AssertionError: False is not true
khi ta so sánh 5 với x. Ta không biết giá trị của x đã dùng trong test là bao nhiêu.

Thay vì assertTrue, hãy dùng các method khác để có message rõ ràng hơn khi test fail, ở ví dụ này, thay vì viết assertTrue(5 > x), ta sẽ dùng assertGreater(5, x), kết quả sẽ rất rõ ràng:

In [6]: class TestFoo(unittest.TestCase):
   ...:     def test_true(self):
   ...:         x = 1
   ...:         self.assertGreater(5, x)
   ...:     def test_false(self):
   ...:         x = 7
   ...:         self.assertGreater(5, x)
   ...:       
In [7]:
In [7]: unittest.main()
F.
======================================================================
FAIL: test_false (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-6-840b5e034319>", line 7, in test_false
    self.assertGreater(5, x)
AssertionError: 5 not greater than 7
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)

5 không lớn hơn 7, message này rõ ràng là cụ thể hơn " False is not true "

Unittest có đủ các method để test các điều kiện :


  • self.assertTrue(7 in thatlist) --> self.assertIn(7, thatlist)
  • self.assertTrue(isinstance(res, list)) --> self.assertIsInstance(res, list)
  • self.assertTrue(res > 0) --> self.assertGreater(res, 0)
  • self.assertTrue(res == [1,2,3,4]) --> self.assertEqual(res, [1,2,3,4])


Tòan bộ các method assert:

$ pydoc unittest | grep assert.*\(self
     |  assertAlmostEqual(self, first, second, places=None, msg=None, delta=None)
     |  assertCountEqual(self, first, second, msg=None)
     |  assertDictContainsSubset(self, subset, dictionary, msg=None)
     |  assertDictEqual(self, d1, d2, msg=None)
     |  assertEqual(self, first, second, msg=None)
     |  assertFalse(self, expr, msg=None)
     |  assertGreater(self, a, b, msg=None)
     |  assertGreaterEqual(self, a, b, msg=None)
     |  assertIn(self, member, container, msg=None)
     |  assertIs(self, expr1, expr2, msg=None)
     |  assertIsInstance(self, obj, cls, msg=None)
     |  assertIsNone(self, obj, msg=None)
     |  assertIsNot(self, expr1, expr2, msg=None)
     |  assertIsNotNone(self, obj, msg=None)
     |  assertLess(self, a, b, msg=None)
     |  assertLessEqual(self, a, b, msg=None)
     |  assertListEqual(self, list1, list2, msg=None)
     |  assertLogs(self, logger=None, level=None)
     |  assertMultiLineEqual(self, first, second, msg=None)
     |  assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None)
     |  assertNotEqual(self, first, second, msg=None)
     |  assertNotIn(self, member, container, msg=None)
     |  assertNotIsInstance(self, obj, cls, msg=None)
     |  assertNotRegex(self, text, unexpected_regex, msg=None)
     |  assertRaises(self, expected_exception, *args, **kwargs)
     |  assertRaisesRegex(self, expected_exception, expected_regex, *args, **kwargs)
     |  assertRegex(self, text, expected_regex, msg=None)
     |  assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None)
     |  assertSetEqual(self, set1, set2, msg=None)
     |  assertTrue(self, expr, msg=None)
     |  assertTupleEqual(self, tuple1, tuple2, msg=None)
     |  assertWarns(self, expected_warning, *args, **kwargs)
     |  assertWarnsRegex(self, expected_warning, expected_regex, *args, **kwargs)
     |  assertAlmostEqual(self, first, second, places=None, msg=None, delta=None)
     |  assertCountEqual(self, first, second, msg=None)
     |  assertDictContainsSubset(self, subset, dictionary, msg=None)
     |  assertDictEqual(self, d1, d2, msg=None)
     |  assertEqual(self, first, second, msg=None)
     |  assertFalse(self, expr, msg=None)
     |  assertGreater(self, a, b, msg=None)
     |  assertGreaterEqual(self, a, b, msg=None)
     |  assertIn(self, member, container, msg=None)
     |  assertIs(self, expr1, expr2, msg=None)
     |  assertIsInstance(self, obj, cls, msg=None)
     |  assertIsNone(self, obj, msg=None)
     |  assertIsNot(self, expr1, expr2, msg=None)
     |  assertIsNotNone(self, obj, msg=None)
     |  assertLess(self, a, b, msg=None)
     |  assertLessEqual(self, a, b, msg=None)
     |  assertListEqual(self, list1, list2, msg=None)
     |  assertLogs(self, logger=None, level=None)
     |  assertMultiLineEqual(self, first, second, msg=None)
     |  assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None)
     |  assertNotEqual(self, first, second, msg=None)
     |  assertNotIn(self, member, container, msg=None)
     |  assertNotIsInstance(self, obj, cls, msg=None)
     |  assertNotRegex(self, text, unexpected_regex, msg=None)
     |  assertRaises(self, expected_exception, *args, **kwargs)
     |  assertRaisesRegex(self, expected_exception, expected_regex, *args, **kwargs)
     |  assertRegex(self, text, expected_regex, msg=None)
     |  assertSequenceEqual(self, seq1, seq2, msg=None, seq_type=None)
     |  assertSetEqual(self, set1, set2, msg=None)
     |  assertTrue(self, expr, msg=None)
     |  assertTupleEqual(self, tuple1, tuple2, msg=None)
     |  assertWarns(self, expected_warning, *args, **kwargs)
     |  assertWarnsRegex(self, expected_warning, expected_regex, *args, **kwargs)

Tham khảo
https://docs.python.org/3/library/unittest.html

Hết.
HVN at http://www.familug.org/ and http://pymi.vn

Đăng ký học #Python tại https://pymi.vn/
Nhập email vào http://invite.pymi.vn/ để nhận thư mời tham gia forum hỏi đáp Python, Django, Golang, Linux ...