【Leetcode】python - 利用 doctest 測試 leetcode python testcase 的優雅寫法 (doctest in class,搭配 class 的用法)

前言

這篇文章基本上內容會與我的另外一篇差不多,可以參考:

https://wongwongnotes-github-io.pages.dev/python/python-testcase/python-doctest/

而這篇文章會更專注在 leetcode 的使用部分。(也會提到前一篇文章沒提到的在 class 中使用的部分)

  • 一樣的前言:

在 python 裡面,我們常需要在程式碼寫完時,測試程式碼功能是否正常,
「doctest」 這個套件雖然冷門,但使用時非常方便,這裡推薦給大家。

你可能會問,這好處在哪?

好處一 - 可以反覆測試不用靠手重新輸入

這應該是最重要的好處了吧,每次要測試只需要多下一個「-v」就行。
看看 leetcode 的那些測資,還有比只需要多下一個「-v」更方便的事情嗎?

好處二 - testcase 直接是註解,不用改code直接貼(欸?

我自己是覺得,他剛好把我們「不要的測試部分」都「用註解包起來了」,
整段 code 可以直接貼上去就能測試了,對懶人來說太方便了啦!

(當然,一個乾淨的code,最好不要有這種莫名其妙的註解啦……)

安裝

使用時我們需要先安裝「doctest」這個套件。
不過通常應該是都已經內建了。

我們可以用 import doctest 來測試看看有沒有 error。

import doctest

使用

在前面的文章中,我們提到了 doctest 在 function 中的基本用法。
這篇我們專門來講 doctest 在 class 中的用法。

範例一 - class 基本用法

class Test:
    """
    >>> a=Test(5)
    >>> a.multiply_by_2()
    10
    """
    def __init__(self, number):
        self._number=number

    def multiply_by_2(self):
        return self._number*2


if __name__ == "__main__":
    import doctest
    doctest.testmod()
  • 在這個例子裡面,當我們執行
python test.py -v
  • 會自動開始檢查:

當 a=Test(5) 時, a.multiply_by_2() 的值是否等於 10

範例二 - leetcode 中的 class 實戰

我們以 leetcode 的第一題為例:
https://leetcode.com/problems/two-sum/

如果想知道答案與詳解,可直接參考我的這篇文章,這邊只講用法:
https://wongwongnotes-github-io.pages.dev/python/python_leetcode/leetcode-python-1/

#
# @lc app=leetcode id=1 lang=python3
#
# [1] Two Sum

#  nums : List[int]
#  target: int

# List[int]

# @lc code=start

class Solution:
    """
    >>> a=Solution()
    >>> a.twoSum([2, 7, 11, 15], 9)
    [0, 1]
    """    
    def twoSum(self, nums, target): # 2 7 11 15
        my_dict = {}
        for idx, ele in enumerate(nums):
            rest = target - ele
            if rest in my_dict:
                return [my_dict[rest], idx]
            else:
                my_dict[ele] = idx # record


if __name__ == "__main__":
    import doctest
    doctest.testmod()

# @lc code=end
  • 在這個例子裡面,當我們執行
python test.py -v
  • 會自動開始檢查:

當 a=Solution() 時,輸入 a.twoSum([2, 7, 11, 15], 9),能不能正確回傳 [0, 1] 。

範例三 - 其實只是範例二的再更簡化

我們把範例二的 testcase 再改寫的簡單一點:

#
# @lc app=leetcode id=1 lang=python3
#
# [1] Two Sum

#  nums : List[int]
#  target: int

# List[int]

# @lc code=start

class Solution:
    """
    >>> Solution().twoSum([2, 7, 11, 15], 9)
    [0, 1]
    """    
    def twoSum(self, nums, target): # 2 7 11 15
        my_dict = {}
        for idx, ele in enumerate(nums):
            rest = target - ele
            if rest in my_dict:
                return [my_dict[rest], idx]
            else:
                my_dict[ele] = idx # record


if __name__ == "__main__":
    import doctest
    doctest.testmod()

# @lc code=end
  • 在這個例子裡面,當我們執行
python test.py -v
  • 會自動開始檢查:

當輸入 Solution().twoSum([2, 7, 11, 15], 9) 時,能不能正確回傳 [0, 1] 。

跟範例二相比,連暫時的 a 都不用宣告了! 越來越乾淨俐落了呢!

  • 此外,在範例三中,我更喜歡的是:

一行 input 與 一行 output,
正完美符合 leetcode testcase 的撰寫方式!

Reference

https://openhome.cc/Gossip/CodeData/PythonTutorial/AssertDocTest.html
https://ithelp.ithome.com.tw/articles/10244417
http://technology-sea.blogspot.com/2012/02/python-doctest-test-case.html
https://stackoverflow.com/questions/2708178/python-using-doctests-for-classes

Licensed under CC BY-NC-SA 4.0