JUnit

說明

此任務會執行 JUnit 測試架構中的測試。您可以在 https://junit.dev.org.tw 找到架構的最新版本。此任務已使用 JUnit 3.0 到 JUnit 3.8.2 進行測試;它無法與 JUnit 3.0 之前的版本搭配使用。它也可以搭配 JUnit 4.x 使用,包括僅使用註解且不使用 JUnit4TestAdapter 的「純」JUnit 4 測試。

注意:此任務依賴 Apache Ant 發行版中未包含的外部程式庫。如需詳細資訊,請參閱 程式庫相依性

注意:如果由這個任務啟動的測試或測試使用的任何程式庫呼叫 java.lang.System.exit()java.lang.Runtime.exit() 等 API,則必須設定 fork=true

注意:您必須提供 junit.jar。您可以執行下列其中一項操作:

  1. junit.jarant-junit.jar 都放入 ANT_HOME/lib
  2. 不要將它們放入 ANT_HOME/lib,而是將它們的位置包含在您的 CLASSPATH 環境變數中。
  3. 使用 -lib 將兩個 JAR 都新增到您的類別路徑。
  4. 在建置檔案的 <taskdef> 中使用 <classpath> 元素指定兩個 JAR 的位置。
  5. ant-junit.jar 保留在 ANT_HOME/lib 中的預設位置,但將 junit.jar 包含在傳遞給 <junit><classpath> 中。自 Ant 1.7 起

請參閱 常見問題集以取得詳細資訊。

測試由巢狀 testbatchtest 標籤定義(請參閱 巢狀元素)。

參數

屬性 說明 必要
printsummary 為每個測試案例列印一行程統計資料。可以接受的值為 onoffwithOutAndErrwithOutAndErron 相同,但也會包含寫入 System.outSystem.err 的測試輸出。 否;預設為 off
fork 在個別 JVM 中執行測試。 否;預設為 off
forkmode 控制在您要分岔一些測試時要建立多少個 JVM。可能的值為 perTest(預設值)、perBatchonceonce 僅為所有測試建立一個 JVM,而 perTest 則為每個 TestCase 類別建立一個新的 JVM。perBatch 為每個巢狀 <batchtest> 建立一個 JVM,並收集所有巢狀 <test>。請注意,只有設定 filtertracehaltonerrorhaltonfailureerrorpropertyfailureproperty 相同設定的測試才能共用一個 JVM,因此即使您將 forkmode 設定為 once,Ant 可能仍必須建立多個 JVM。此屬性會忽略未分岔到新 JVM 的測試。自 Ant 1.6.2 起 否;預設為 perTest
haltonerror 如果測試執行期間發生錯誤,停止建置程序。 否;預設為 off
errorproperty 在發生錯誤時設定的屬性名稱。
haltonfailure 如果測試失敗,停止建置程序(錯誤也視為失敗)。 否;預設為 off
failureproperty 在發生失敗時設定的屬性名稱(錯誤也視為失敗)。
filtertrace 從錯誤和失敗堆疊追蹤中濾出 JUnit 和 Ant 堆疊框架。 否;預設為 on
timeout 如果個別測試未在給定時間內完成(以毫秒為單位),取消測試。如果 forkoff,則忽略。在同一個 JVM 內執行多個測試時(請參閱 forkMode),timeout 適用於所有測試一起使用的時間,而不是個別測試。
maxmemory 分配給分岔 JVM 的最大記憶體量。如果 forkoff,則忽略。注意:如果在某些測試中收到 java.lang.OutOfMemoryError: Java heap space,則需要增加大小,例如 maxmemory=128m
jvm 用於呼叫 JVM 的指令。指令由 java.lang.Runtime.exec() 解析。 否;預設為 java,如果 forkfalse,則忽略。
dir 呼叫 JVM 的目錄。 否,如果 forkfalse,則忽略。
newenvironment 指定新的環境變數時,不要傳播舊環境。 否;預設為 false,如果 forkfalse,則忽略。
includeantruntime 在分岔模式中,隱式將執行測試和 JUnit 所需的 Ant 類別新增到類別路徑。 否;預設為 true
showoutput 將測試產生的任何輸出傳送至 Ant 的記錄系統,以及格式化程式。 否;預設只有格式化程式會接收輸出
outputtoformatters 將測試產生的任何輸出傳送至測試格式化程式。自 Ant 1.7.0 起 否;預設為 true
tempdir Ant 應放置暫存檔案的位置。自 Ant 1.6 起 否;預設為專案的 basedir
reloading 是否應為每個測試案例實例化新的類別載入器。
如果 fork 設為 true,則忽略。自 Ant 1.6 起
否;預設為 true
clonevm 如果設為 true,則分岔 JVM 的所有系統屬性和 bootclasspath 將與執行 Ant 的 JVM 相同。自 Ant 1.7 起 否;預設為 false,如果 forkfalse,則忽略。
logfailedtests 當 Ant 執行多個測試,且不會在錯誤或失敗時停止,它會為每個失敗的測試記錄「FAILED」訊息到其記錄系統。如果您將此選項設定為 false,訊息將不會被記錄,而且您必須依賴格式化器輸出才能找到失敗的測試。自 Ant 1.8.0 起
enableTestListenerEvents Ant 是否應該在詳細程度層級將關於正在執行的測試的精細資訊傳送至 Ant 的記錄系統。此類事件可用於自訂測試監聽器來顯示測試的進度。
自 Ant 1.8.2 起Ant 1.7.0 至 1.8.1 的行為就像此屬性預設為 true
否;預設為 false,可由 神奇屬性 覆寫
threads 執行測試的執行緒數目。
當指定此屬性時,測試將在執行緒之間任意分割。
需要使用 perTest 選項分岔測試才能運作。
自 Ant 1.9.4 起

透過使用 errorpropertyfailureproperty 屬性,可以在發生失敗時執行設定工作(例如啟動外部伺服器)、執行測試、清理,並讓建置失敗。

在報告錯誤和失敗堆疊追蹤之前,filtertrace 屬性會將它們濃縮。它與純文字和 XML 格式化器搭配使用。它會篩選掉以下列字串樣式開頭的任何行

   "junit.framework.TestCase"
   "junit.framework.TestResult"
   "junit.framework.TestSuite"
   "junit.framework.Assert."
   "junit.swingui.TestRunner"
   "junit.awtui.TestRunner"
   "junit.textui.TestRunner"
   "java.lang.reflect.Method.invoke("
   "sun.reflect."
   "org.apache.tools.ant."
   "org.junit."
   "junit.framework.JUnit4TestAdapter"
   " more"

以巢狀元素指定參數

<junit> 任務支援一個巢狀 <classpath> 元素,它代表 類似的路徑結構

自 Ant 1.7 起,此類別路徑可用於參考 junit.jar,以及您的測試和受測程式碼。

jvmarg

如果 forktrue,可以透過巢狀 <jvmarg> 元素將其他參數傳遞給新的 JVM。例如

<junit fork="yes">
  <jvmarg value="-Dfoo=bar"/>
  ...
</junit>

會在沒有 JIT 的 JVM 中執行測試。

<jvmarg> 允許使用 命令列引數 中描述的所有屬性。

sysproperty

使用巢狀 <sysproperty> 元素來指定類別所需的系統屬性。這些屬性會在測試執行期間提供給 JVM(如果 fork=true,則為 Ant 的 JVM 或分岔的 JVM)。此元素的屬性與 環境變數 相同。

<junit fork="no">
  <sysproperty key="basedir" value="${basedir}"/>
  ...
</junit>

會在 Ant 的 JVM 中執行測試,並讓 basedir 屬性提供給測試。

syspropertyset

自 Ant 1.6 起

您可以使用 syspropertyset 指定一組屬性,作為系統屬性使用。

env

可以透過嵌套的 <env> 元素,指定要傳遞給分岔 JVM 的環境變數。有關 <env> 元素屬性的說明,請參閱 exec 任務中的說明。

如果 fork=false,將會忽略設定。

bootclasspath

自 Ant 1.6 起.

可以使用這個 類似路徑的結構 指定引導類別檔的位置,如果 forkfalse 或目標 JVM 不支援(例如 Java 1.1),將會忽略。

permissions

自 Ant 1.6 起.

注意:
在 Java 18 及更高版本上執行時,不再支援此元素。有關詳細資訊,請參閱 permissions

可以在執行類別期間,透過嵌套的 permissions 元素撤銷和授予安全性權限。有關更多資訊,請參閱 permissions

如果 fork=true,將會忽略設定。

assertions

自 Ant 1.6 起.

您可以使用 <assertions> 子元素控制啟用 Java 1.4 斷言。

目前在非分岔模式中會忽略斷言陳述。

modulepath

自 Ant 1.9.8 起

可以使用這個 類似路徑的結構 指定模組的位置。
modulepath 需要將 fork 設定為 true

upgrademodulepath

自 Ant 1.9.8 起

可以使用這個 類似路徑的結構 指定取代執行時間映像中可升級模組的模組位置。
upgrademodulepath 需要將 fork 設定為 true

formatter

測試結果可以用不同的格式列印。輸出將始終傳送到檔案,除非您將 usefile 屬性設定為 false。檔案名稱由測試名稱決定,並可透過 <test>outfile 屬性設定。

有四種預先定義好的格式化程式,一個會以 XML 格式列印測試結果,另一個會發出純文字。名為 brief 的格式化程式只會列印失敗測試案例的詳細資訊,而 plain 則會為所有測試案例提供簡要的統計資料行。可以指定需要實作 org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter 的自訂格式化程式。

如果您使用 XML 格式化程式,它可能不會包含您的測試所寫入的相同輸出,因為某些字元在 XML 文件中是非法的,因此會被捨棄。

第四個名為 failure 的格式化程式(自 Ant 1.8.0 起)會收集所有失敗的 testXXX() 方法,並建立一個新的 TestCase,只委派這些失敗的方法。名稱和位置可透過 Java 系統屬性或 Ant 屬性 ant.junit.failureCollector 指定。該值必須指向目錄和結果類別的名稱(沒有字尾)。預設為 java-tmp-dir/FailedTests

屬性 說明 必要
類型 使用預先定義好的格式化程式(xmlplainbrieffailure)。 這些選項中只能有一個
類別名稱 自訂格式化程式類別的名稱。
副檔名 要附加到輸出檔名的副檔名。 如果已使用 類別名稱,則為是
使用檔案 布林值,用於決定是否應將輸出傳送至檔案。 否;預設為 true
if 只有在設定指定屬性的情況下,才使用格式化程式 if 否;預設為 true
unless 只有在未設定指定屬性的情況下,才使用格式化程式 if 否;預設為 true

測試

定義單一測試類別。

屬性 說明 必要
名稱 測試類別的名稱。
方法 要執行的測試案例方法名稱的逗號分隔清單。自 1.8.2 起

方法 屬性可在下列情況中發揮作用

  • 測試方法已失敗,您想要重新執行測試方法來測試修正程式,或是在 Java 除錯程式中重新執行測試,而不用等待其他(可能執行時間較長的)測試方法完成。
  • 一個或多個測試方法執行的速度比預期慢,您想要在 Java 分析器中重新執行它們(而不用在執行其他測試方法時產生分析器負擔)。

如果使用了 方法 屬性,但未指定任何測試方法,則不會執行組件中的任何測試方法。

否;預設會執行組件中的所有測試方法
fork 在一個獨立的 JVM 中執行測試。覆寫在 <junit> 中設定的值。
haltonerror 如果在測試執行期間發生錯誤,則停止建置程序。覆寫在 <junit> 中設定的值。
errorproperty 在發生錯誤時設定的屬性名稱。覆寫在 <junit> 中設定的值。
haltonfailure 如果測試失敗,則停止建置程序(錯誤也視為失敗)。覆寫在 <junit> 中設定的值。
failureproperty 在發生失敗時設定的屬性名稱(錯誤也視為失敗)。覆寫在 <junit> 中設定的值。
filtertrace 從錯誤和失敗堆疊追蹤中濾出 JUnit 和 Ant 堆疊框架。覆寫在 <junit> 中設定的值。 否;預設為 on
todir 寫入報告的目錄。 否;預設為目前目錄
outfile 測試結果的基本名稱。完整檔名為 outfile.formatter 否;預設為 TEST-name
if 僅在設定指定屬性的情況下執行測試 if the named property is set
unless 僅在未設定指定屬性的情況下執行測試 if the named property is not set
skipNonTests 不要將不包含 JUnit 測試的任何類別傳遞給測試執行器。這可防止非測試出現在測試結果中的測試錯誤中。
透過尋找未延伸 junit.framework.TestCase 的具體類別中任何方法上的 @Test 註解,或在延伸 junit.framework.TestCase 的具體類別中以 test 開頭的 public/protected 方法,來識別測試。標記為 JUnit 4 org.junit.runner.RunWithorg.junit.runner.Suite.SuiteClasses 註解的類別也會傳遞給 JUnit 執行,任何具有 public/protected 無參數 suite() 方法的類別也是如此。
否;預設為 false

測試可透過巢狀 <formatter> 元素定義自己的格式器。

batchtest

根據模式比對定義多個測試。

batchtest 從任何數量的巢狀 資源收集包含的 資源集合。然後,它會為每個以 .java.class 結尾的資源產生一個測試類別名稱。

任何類型的資源集合都支援作為巢狀元素,在 Ant 1.7 之前,僅支援 <fileset>

屬性 說明 必要
fork 在一個獨立的 JVM 中執行測試。覆寫在 <junit> 中設定的值。
haltonerror 如果在測試執行期間發生錯誤,則停止建置程序。覆寫在 <junit> 中設定的值。
errorproperty 在發生錯誤時設定的屬性名稱。覆寫在 <junit> 中設定的值。
haltonfailure 如果測試失敗,則停止建置程序(錯誤也視為失敗)。覆寫在 <junit> 中設定的值。
failureproperty 在發生失敗時設定的屬性名稱(錯誤也視為失敗)。覆寫在 <junit> 中設定的值
filtertrace 從錯誤和失敗堆疊追蹤中濾出 JUnit 和 Ant 堆疊框架。覆寫在 <junit> 中設定的值。 否;預設為 on
todir 寫入報告的目錄。 否;預設為目前目錄
if 僅在設定指定屬性的情況下執行測試 if the named property is set
unless 僅在未設定指定屬性的情況下執行測試 if the named property is not set
skipNonTests 不要將不包含 JUnit 測試的任何類別傳遞給測試執行器。這可防止非測試出現在測試結果中的測試錯誤中。
透過尋找未延伸 junit.framework.TestCase 的具體類別中任何方法上的 @Test 註解,或在延伸 junit.framework.TestCase 的具體類別中以 test 開頭的 public/protected 方法,來識別測試。標記為 JUnit 4 org.junit.runner.RunWithorg.junit.runner.Suite.SuiteClasses 註解的類別也會傳遞給 JUnit 執行,任何具有 public/protected 無參數 suite() 方法的類別也是如此。
否;預設為 false

批次測試可透過巢狀的 <formatter> 元素定義自己的格式化程式。

分岔測試和 tearDown()

如果分岔測試逾時,Ant 會終止它所建立的 JVM 程序,這表示測試的 tearDown() 方法可能永遠不會被呼叫。如果分岔的 JVM 因其他原因而崩潰,情況也是如此。

自 Ant 1.8.0 起,Ant 會隨附一個特殊格式化程式,它會嘗試載入分岔的 JVM 中的測試案例,並呼叫該類別的 tearDown() 方法。此格式化程式有以下限制

如果格式化程式辨識出不相容的 forkModesuite() 方法,或無法載入測試類別,它會在不發出任何訊息的情況下執行任何動作。

格式化程式不會對未分岔或未導致逾時或 JVM 崩潰的測試產生任何影響。

若要啟用格式化程式,請新增一個類似於

<formatter classname="org.apache.tools.ant.taskdefs.optional.junit.TearDownOnVmCrash"
           usefile="false"/>

formatter 到您的 junit 工作。

ant.junit.enabletestlistenerevents 魔術屬性

自 Ant 1.8.2 起,工作中的 enableTestListenerEvents 屬性會控制是否將細部記錄訊息傳送至工作的詳細記錄。除了此屬性之外,Ant 會諮詢屬性 ant.junit.enabletestlistenerevents,而屬性的值會覆寫屬性的設定。

此屬性存在,以便執行 Ant 的容器依賴額外記錄事件,可確保即使建置檔案停用它們,它們也會被產生。

範例

在同一個 VM 中執行在 my.test.TestCase 中定義的測試。除非測試失敗,否則不會產生輸出。

<junit>
    <test name="my.test.TestCase"/>
</junit>

在一個獨立的 JVM 中執行在 my.test.TestCase 中定義的測試。在測試結束時,將會列印一行摘要。可在 TEST-my.test.TestCase.txt 中找到測試的詳細報告。如果測試失敗,將會停止建置程序。

<junit printsummary="yes" fork="yes" haltonfailure="yes">
    <formatter type="plain"/>
    <test name="my.test.TestCase"/>
</junit>

在同一個 JVM 中執行 my.test.TestCase,忽略指定的 CLASSPATH;如果此測試失敗,只會列印警告。除了純文字測試結果外,此測試的 XML 結果將會輸出至 result.xml。然後,對於在為 ${src.tests} 定義的目錄中的每個符合檔案,會在一個獨立的 JVM 中執行測試。如果測試失敗,將會中止建置程序。結果會收集在名為 TEST-name.txt 的檔案中,並寫入 ${reports.tests}

<junit printsummary="yes" haltonfailure="yes">
    <classpath>
        <pathelement location="${build.tests}"/>
        <pathelement path="${java.class.path}"/>
    </classpath>

    <formatter type="plain"/>

    <test name="my.test.TestCase" haltonfailure="no" outfile="result">
        <formatter type="xml"/>
    </test>

    <batchtest fork="yes" todir="${reports.tests}">
        <fileset dir="${src.tests}">
            <include name="**/*Test*.java"/>
            <exclude name="**/AllTests.java"/>
        </fileset>
    </batchtest>
</junit>

在第一次執行時,所有測試都會透過 <batchtest/> 元素收集。它的 plain 格式化程式會在主控台上顯示輸出。failure 格式化程式會在 ${build.dir}/failingTests/FailedTests.java 中建立一個 Java 原始檔,它會延伸 junit.framework.TestCase,並從 suite() 方法傳回失敗測試的測試套件。
在第二次執行時,收集器類別存在,並且會執行單一的 <test/>,而不是 <batchtest/>。因此,只會重新執行失敗的測試案例。兩個巢狀格式化程式用於顯示(給使用者)和更新收集器類別。

<target name="test">
    <property name="collector.dir" value="${build.dir}/failingTests"/>
    <property name="collector.class" value="FailedTests"/>
    <!-- Delete 'old' collector classes -->
    <delete>
        <fileset dir="${collector.dir}" includes="${collector.class}*.class"/>
    </delete>
    <!-- compile the FailedTests class if present -->
    <javac srcdir="${collector.dir}" destdir="${collector.dir}"/>
    <available file="${collector.dir}/${collector.class}.class" property="hasFailingTests"/>
    <junit haltonerror="false" haltonfailure="false">
        <sysproperty key="ant.junit.failureCollector" value="${collector.dir}/${collector.class}"/>
        <classpath>
            <pathelement location="${collector.dir}"/>
        </classpath>
        <batchtest todir="${collector.dir}" unless="hasFailingTests">
            <fileset dir="${collector.dir}" includes="**/*.java" excludes="**/${collector.class}.*"/>
            <!-- for initial creation of the FailingTests.java -->
            <formatter type="failure"/>
            <!-- I want to see something ... -->
            <formatter type="plain" usefile="false"/>
        </batchtest>
        <test name="FailedTests" if="hasFailingTests">
            <!-- update the FailingTests.java -->
            <formatter type="failure"/>
            <!-- again, I want to see something -->
            <formatter type="plain" usefile="false"/>
        </test>
    </junit>
</target>

在由 platform.java 屬性指定的 fork JVM 中,以白盒測試方式執行 my.test.TestCase。JUnit 函式庫是未命名模組的一部分,而受測專案和所需的模組則在模組路徑上。測試沒有 module-info 檔案,並在由 module.name 屬性指定的專案模組中執行。
--patch-module Java 選項會在由 module.name 屬性指定的模組中執行建置到 ${build.test.classes} 的測試。
--add-modules Java 選項會啟用受測模組。
--add-reads Java 選項會讓包含 JUnit 的未命名模組可供受測模組讀取。
--add-exports Java 選項會讓未輸出的測試套件 my.test 可供包含 JUnit 的未命名模組存取。

<junit fork="true"
       jvm="${platform.java}">
    <jvmarg line="--patch-module ${module.name}=${build.test.classes}"/>
    <jvmarg line="--add-modules ${module.name}"/>
    <jvmarg line="--add-reads ${module.name}=ALL-UNNAMED"/>
    <jvmarg line="--add-exports ${module.name}/my.test=ALL-UNNAMED"/>
    <classpath>
        <pathelement path="${libs.junit}"/>
    </classpath>
    <modulepath>
        <pathelement path="${modules}:${build.classes}"/>
    </modulepath>
    <formatter type="plain"/>
    <test name="my.test.TestCase"/>
</junit>

在由 platform.java 屬性指定的 fork JVM 中,以黑盒測試方式執行 my.test.TestCase。JUnit 函式庫用作自動模組。測試的 module-info 需要受測模組和 JUnit。
--add-modules Java 選項會啟用測試模組。
--add-exports Java 選項會讓未輸出的測試套件 my.test 可供 JUnit 模組和 Ant 的測試執行器存取。另一個可能性是透過 exports my.test 指令在測試的 module-info 中輸出測試套件。

<junit fork="true"
       jvm="${platform.java}">
    <jvmarg line="--add-modules ${test.module.name}"/>
    <jvmarg line="--add-exports ${test.module.name}/my.test=junit,ALL-UNNAMED"/>
    <modulepath>
        <pathelement path="${modules}:${build.classes}:${libs.junit}"/>
    </modulepath>
    <formatter type="plain"/>
    <test name="my.test.TestCase"/>
</junit>