檢視原始碼 Common Test 的屬性測試支援:ct_property_test

一般

Common Test 屬性測試支援 (ct_property_test) 是一個輔助工具,用於在 Common Test 測試套件中執行基於屬性的測試工具。

以下內容假設您已具備基於屬性的測試的基本知識。同時也假設您已安裝下列至少一個基於屬性的測試工具,並可在程式庫路徑中取得:

支援的功能

ct_property_test 模組會執行下列操作:

  • 編譯 property_test 子目錄中包含屬性測試的檔案
  • 使用第一個找到的屬性測試工具測試這些檔案中的屬性。
  • 將結果(即輸出)儲存在常見的 Common Test 日誌中

入門範例

假設我們要測試 lists:sort/1 函式。

我們需要一個屬性來測試該函式。一般來說,我們會在應用程式的 test 目錄中建立 property_test/ct_prop.erl 模組

-module(ct_prop).
-export([prop_sort/0]).

%%% This will include the .hrl file for the installed testing tool:
-include_lib("common_test/include/ct_property_test.hrl").

%%% The property we want to check:
%%%   For all possibly unsorted lists,
%%%   the result of lists:sort/1 is sorted.
prop_sort() ->
    ?FORALL(UnSorted, list(),
            is_sorted(lists:sort(UnSorted))
           ).

%%% Function to check that a list is sorted:
is_sorted([]) ->
    true;
is_sorted([_]) ->
    true;
is_sorted([H1,H2|SortedTail]) when H1 =< H2 ->
    is_sorted([H2|SortedTail]);
is_sorted(_) ->
    false.

我們也需要一個 CommonTest 測試套件

-module(ct_property_test_SUITE).
-compile(export_all). % Only in tests!

-include_lib("common_test/include/ct.hrl").

all() -> [prop_sort
         ].

%%% First prepare Config and compile the property tests for the found tool:
init_per_suite(Config) ->
    ct_property_test:init_per_suite(Config).

end_per_suite(Config) ->
    Config.

%%%================================================================
%%% Test suites
%%%
prop_sort(Config) ->
    ct_property_test:quickcheck(
      ct_prop:prop_sort(),
      Config
     ).

我們像往常一樣執行它,例如使用 OS shell 中的 ct_run

..../test$ ct_run -suite ct_property_test_SUITE
.....
Common Test: Running make in test directories...

TEST INFO: 1 test(s), 1 case(s) in 1 suite(s)

Testing lib.common_test.ct_property_test_SUITE: Starting test, 1 test cases

----------------------------------------------------
2019-12-18 10:44:46.293
Found property tester proper
at "/home/X/lib/proper/ebin/proper.beam"


----------------------------------------------------
2019-12-18 10:44:46.294
Compiling in "/home/..../test/property_test"
  Deleted:   ["ct_prop.beam"]
  ErlFiles:  ["ct_prop.erl"]
  MacroDefs: [{d,'PROPER'}]

Testing lib.common_test.ct_property_test_SUITE: TEST COMPLETE, 1 ok, 0 failed of 1 test cases

....

一個具狀態測試的範例

假設有一個測試會產生一些平行的具狀態命令,並執行 300 個測試

prop_parallel(Config) ->
    numtests(300,
             ?FORALL(Cmds, parallel_commands(?MODULE),
                     begin
                         RunResult = run_parallel_commands(?MODULE, Cmds),
                         ct_property_test:present_result(?MODULE, Cmds, RunResult, Config)
                     end)).

ct_property_test:present_result/4 是一個輔助函式,用於在 CommonTest 日誌檔案中列印一些統計資訊。

我們的範例測試可以是一個簡單的 FTP 伺服器測試,我們執行 get、put 和 delete 請求,其中一些是平行執行的。預設情況下,結果有三個部分

*** User 2019-12-11 13:28:17.504 ***

Distribution sequential/parallel

 57.7% sequential
 28.0% parallel_2
 14.3% parallel_1



*** User 2019-12-11 13:28:17.505 ***

Function calls

 44.4% get
 39.3% put
 16.3% delete



*** User 2019-12-11 13:28:17.505 ***

Length of command sequences

Range  : Number in range
-------:----------------
 0 -  4:    8    2.7%  <-- min=3
 5 -  9:   44   14.7%
10 - 14:   74   24.7%
15 - 19:   60   20.0%  <-- mean=18.7 <-- median=16.0
20 - 24:   38   12.7%
25 - 29:   26    8.7%
30 - 34:   19    6.3%
35 - 39:   19    6.3%
40 - 44:    8    2.7%
45 - 49:    4    1.3%  <-- max=47
        ------
          300

第一部分 - 分佈循序/平行 - 顯示 parallel_commands/1 結果的循序和平行部分的分配。有關此函式的說明,請參閱任何屬性測試工具。該表顯示,在所有命令(在本例中為 get 和 put)中,57.7% 在平行部分之前的循序部分執行,28.0% 在第一個平行清單中執行,其餘在第二個平行清單中執行。

第二部分 - 函式呼叫 - 顯示產生的命令清單中三個呼叫的分佈。我們看到所有三個呼叫都已執行。如果我們認為我們也產生了第四個呼叫,像這樣的表格會顯示我們失敗了。

第三個也是最後一個部分 - 命令序列的長度 - 顯示產生命令序列的統計資訊。我們看到最短的清單有三個元素,而最長的清單有 47 個元素。還會顯示平均值和中位數。此外,例如我們可以看到只有 2.7% 的清單(即八個清單)只有三個或四個元素。