日前在Girls In Tech的Pair Programming活動擔任mentor
因為mentor短缺, 除了拉人以外, 還同時準備了兩門語言教材(Android、Python)
練習題主軸如下 :

  1. hello world
  2. input / output (string)
  3. control flow (if…else)

雖然設定的題目很簡單
但已經可以做非常多的基礎觀念教學
趁這個機會, 決定繼續延伸深入學習 Python

根據以往學習語言的經驗
個人習慣用移植改寫的方式來快速上手新語言 所以決定採用之前在 泰迪軟體 所上的 單元測試課程教材做練習 一方面熟悉Python, 一方面複習單元測試

採用工具

Intellij 設定

若要於Intellij運行Python, 必須先安裝套件才能建立Python專案

File > Settings > Plugins > Browse repositories
搜尋框輸入 : python > Install
重新啟動Intellij

安裝完Python plugin後, 便可以建立Python專案
在建立專案後, 別忘記要設定Python SDK的位置 (沒有設定正確路徑便無法運行喔)

File > Project structure > Project > 選擇安裝的Python版本

Python 的單元測試架構

因為要練習的專案還包括單元測試
所以仿造之前練習JUnit的架構
分為 src(原始碼) 及 test(測試原始碼) 兩個資料夾各別存放相對應的原始碼

舉例來說 test_src00即是 src00 的單元測試原始碼

範例

決定架構後, 開始練習
由於會分許多不同的練習題目, 所以建立package區分功能 (src 及 test 也分別以package的方式建立)

在要建立的資料夾內滑鼠右鍵 > New > Python Package
輸入package name

依據以下結構個別於src及test 資料夾內建立好 a00 package

於src的 a00 package內新增 python file, 命名為 Math.py
程式碼範例如下

import math

class Math:

    def solver(self, a, b, c):
        d = b ** 2 - 4 * a * c
        if d >= 0:
            disc = math.sqrt(d)
            root1 = (-b + disc) / (2 * a)
            root2 = (-b - disc) / (2 * a)
            print(root1, root2)
        else:
            raise Exception

Math().solver(2, 1, 0)

於test的a00 package內新增 python file, 命名為 test_math.py
也可以對著src的class name滑鼠右鍵 > Go To > Test > 輸入路徑 來建立
程式碼範例如下

from unittest import TestCase
from src.a00.Math import Math


class TestSolver(TestCase):

    def test_negative_discr(self):
        s = Math()
        self.assertRaises(Exception,s.solver,2,1,2)

現在可以運行單元測試看看結果了
我的習慣是 直接 ctrl + shift + F10
也可以點選test file > 右鍵 > Run ‘Unittests in test_math.py’

如果要運行所有單元測試, 便點選test資料夾 > 右鍵 > Run ‘Unittests in test’

運行結果

主視窗下會直接顯示單元測試的運行結果
左下方為全部測試的樹狀結構圖
綠色表示pass, 紅色表示fail

如果不習慣使用IDE 其實也是可以直接使用command line下達指令

$cd projectName
$python -m unittest testmodule

testmodule為test file的檔名
若要運行所有測試, 則帶入test資料夾名稱
(如果運行後沒有找到測試, 則需要增加discover指令, 他會找尋該資料夾下所有測試)

$python -m unittest discover testFolder

注意

__init__.py 檔案預設空白
是一個用來辨認該資料夾為package的檔案
也可以在裡面寫些用來初始化的程式碼
或制定該package需要包進那些檔案 運行時, 會優先尋找__init__.py檔案
然後執行該層資料夾中的程式碼
__init__.py的說明