Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 在erlang中测试_Concurrency_Parallel Processing_Erlang_Erlang Shell - Fatal编程技术网

Concurrency 在erlang中测试

Concurrency 在erlang中测试,concurrency,parallel-processing,erlang,erlang-shell,Concurrency,Parallel Processing,Erlang,Erlang Shell,我试着在Erlang学习测试。我使用了目前一个tic-tac-toe游戏的代码库。这是一个两人游戏(让我们称之为一对玩家)。我基本上想检查当多对玩家同时玩这个游戏时会发生什么。 因此,我尝试编写一个简单的基本模块来测试它,名为testing,如下所示: -module(testing). %% ==================================================================== %% API functions %% ============

我试着在Erlang学习测试。我使用了目前一个tic-tac-toe游戏的代码库。这是一个两人游戏(让我们称之为一对玩家)。我基本上想检查当多对玩家同时玩这个游戏时会发生什么。 因此,我尝试编写一个简单的基本模块来测试它,名为
testing
,如下所示:

-module(testing).

%% ====================================================================
%% API functions
%% ====================================================================
-export([all/0]).



%% ====================================================================
%% Internal functions
%% ====================================================================
all()->

    test1(),
    timer:sleep(75),
    test2(),
    timer:sleep(75),
    test3(),
    timer:sleep(75).





test1()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test1 is ~p~n",
              [G_serv_Output1]),
    Abhishek=gameclient:login("Abhishek"),
    Dharun=gameclient:login("Dharun"),


    gameclient:new_game(Abhishek,"Dharun"),

    timer:sleep(5),

    gameclient:make_move(Abhishek,"Dharun", a1),
    timer:sleep(5),
    gameclient:make_move(Dharun,"Abhishek", b2),
    timer:sleep(5),
    gameclient:make_move(Abhishek,"Dharun", a2),
    timer:sleep(5), 
    gameclient:make_move(Dharun,"Abhishek", c3),
    timer:sleep(5),
    gameclient:make_move(Abhishek,"Dharun", a3).




test2()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test2 is ~p~n",
               [G_serv_Output1]),
    Abhijeet=gameclient:login("Abhijeet"),
    Ranjan=gameclient:login("Ranjan"),


    gameclient:new_game(Abhijeet,"Ranjan"),
    timer:sleep(5),

    gameclient:make_move(Abhijeet,"Ranjan", a1),
    timer:sleep(5),
    gameclient:make_move(Ranjan,"Abhijeet", b2),
    timer:sleep(5),
    gameclient:make_move(Abhijeet,"Ranjan", a2),
    timer:sleep(5), 
    gameclient:make_move(Ranjan,"Abhijeet", c3),
    timer:sleep(5),
    gameclient:make_move(Abhijeet,"Ranjan", a3).





test3()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test3 is ~p~n",
              [G_serv_Output1]),
    Bana=gameclient:login("Bana"),
    Sagar=gameclient:login("Sagar"),


    gameclient:new_game(Bana,"Sagar"),
    timer:sleep(5),

    gameclient:make_move(Bana,"Sagar", a1),
    timer:sleep(5),
    gameclient:make_move(Sagar,"Bana", b2),
    timer:sleep(5),
    gameclient:make_move(Bana,"Sagar", a2),
    timer:sleep(5), 
    gameclient:make_move(Sagar,"Bana", c3),
    timer:sleep(5),
    gameclient:make_move(Bana,"Sagar", a3).
new_game(Pid) ->
    Pid ! {new_game}.

make_move(Pid, Move) -> 

    Pid ! { make_move, Move }.
loop(Name) ->
    receive
        { new_game} ->
            gameserver:new_game(Name),
            loop(Name);
        { make_move, Move } ->
            gameserver:make_move(Name, Move),
            loop(Name)

    end.
-module(testing2).
-include_lib("common_test/include/ct.hrl").
%% ====================================================================
%% API functions
%% ====================================================================
-export([all/0, groups/0, init_per_group/2, end_per_group/2]).
-export([test1/1,test2/1]).



%% ====================================================================
%% Internal functions
%% ====================================================================
all() -> [{group, session}].

groups() -> [{session,
              [],
              [{group, clients}]},
             {clients,
              [parallel, {repeat, 1}],
              [test1, test2]}].

init_per_group(session, Config) ->
   gameserver:start(),
    Config;
init_per_group(_, Config) ->
    Config.

end_per_group(session, _Config) ->
    gameserver:stop();
end_per_group(_, _Config) ->
    ok.

test1(_Config)->



Abhishek=gameclient:login("Abhishek"),
Dharun=gameclient:login("Dharun"),


gameclient:new_game(Abhishek),

    timer:sleep(10),

    gameclient:make_move(Abhishek, a1),
    timer:sleep(10),
    gameclient:make_move(Dharun, b2),
    timer:sleep(10),
    gameclient:make_move(Abhishek, a2),
    timer:sleep(10),    
    gameclient:make_move(Dharun, c3),
    timer:sleep(10),
    gameclient:make_move(Abhishek, a3).





test2(_Config)->



Abhijeet=gameclient:login("Abhijeet"),
Ranjan=gameclient:login("Ranjan"),


gameclient:new_game(Abhijeet),
    timer:sleep(10),

    gameclient:make_move(Abhijeet, a1),
    timer:sleep(10),
    gameclient:make_move(Ranjan, b2),
    timer:sleep(10),
    gameclient:make_move(Abhijeet, a2),
    timer:sleep(10),    
    gameclient:make_move(Ranjan, c3),
    timer:sleep(10),
    gameclient:make_move(Abhijeet, a3).
三次测试都进行得很好,我看到三场比赛都完成了

然后我注意到像
gameclient:new_game/2
gameclient:new_game/3
这样的函数也将
对手名称
作为输入,我决定将其删除,因此我将
new_game/2更改为new_game/1
并在
gameclient
中将
make_move/3更改为make_move/2
,如下:

-module(testing).

%% ====================================================================
%% API functions
%% ====================================================================
-export([all/0]).



%% ====================================================================
%% Internal functions
%% ====================================================================
all()->

    test1(),
    timer:sleep(75),
    test2(),
    timer:sleep(75),
    test3(),
    timer:sleep(75).





test1()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test1 is ~p~n",
              [G_serv_Output1]),
    Abhishek=gameclient:login("Abhishek"),
    Dharun=gameclient:login("Dharun"),


    gameclient:new_game(Abhishek,"Dharun"),

    timer:sleep(5),

    gameclient:make_move(Abhishek,"Dharun", a1),
    timer:sleep(5),
    gameclient:make_move(Dharun,"Abhishek", b2),
    timer:sleep(5),
    gameclient:make_move(Abhishek,"Dharun", a2),
    timer:sleep(5), 
    gameclient:make_move(Dharun,"Abhishek", c3),
    timer:sleep(5),
    gameclient:make_move(Abhishek,"Dharun", a3).




test2()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test2 is ~p~n",
               [G_serv_Output1]),
    Abhijeet=gameclient:login("Abhijeet"),
    Ranjan=gameclient:login("Ranjan"),


    gameclient:new_game(Abhijeet,"Ranjan"),
    timer:sleep(5),

    gameclient:make_move(Abhijeet,"Ranjan", a1),
    timer:sleep(5),
    gameclient:make_move(Ranjan,"Abhijeet", b2),
    timer:sleep(5),
    gameclient:make_move(Abhijeet,"Ranjan", a2),
    timer:sleep(5), 
    gameclient:make_move(Ranjan,"Abhijeet", c3),
    timer:sleep(5),
    gameclient:make_move(Abhijeet,"Ranjan", a3).





test3()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test3 is ~p~n",
              [G_serv_Output1]),
    Bana=gameclient:login("Bana"),
    Sagar=gameclient:login("Sagar"),


    gameclient:new_game(Bana,"Sagar"),
    timer:sleep(5),

    gameclient:make_move(Bana,"Sagar", a1),
    timer:sleep(5),
    gameclient:make_move(Sagar,"Bana", b2),
    timer:sleep(5),
    gameclient:make_move(Bana,"Sagar", a2),
    timer:sleep(5), 
    gameclient:make_move(Sagar,"Bana", c3),
    timer:sleep(5),
    gameclient:make_move(Bana,"Sagar", a3).
new_game(Pid) ->
    Pid ! {new_game}.

make_move(Pid, Move) -> 

    Pid ! { make_move, Move }.
loop(Name) ->
    receive
        { new_game} ->
            gameserver:new_game(Name),
            loop(Name);
        { make_move, Move } ->
            gameserver:make_move(Name, Move),
            loop(Name)

    end.
-module(testing2).
-include_lib("common_test/include/ct.hrl").
%% ====================================================================
%% API functions
%% ====================================================================
-export([all/0, groups/0, init_per_group/2, end_per_group/2]).
-export([test1/1,test2/1]).



%% ====================================================================
%% Internal functions
%% ====================================================================
all() -> [{group, session}].

groups() -> [{session,
              [],
              [{group, clients}]},
             {clients,
              [parallel, {repeat, 1}],
              [test1, test2]}].

init_per_group(session, Config) ->
   gameserver:start(),
    Config;
init_per_group(_, Config) ->
    Config.

end_per_group(session, _Config) ->
    gameserver:stop();
end_per_group(_, _Config) ->
    ok.

test1(_Config)->



Abhishek=gameclient:login("Abhishek"),
Dharun=gameclient:login("Dharun"),


gameclient:new_game(Abhishek),

    timer:sleep(10),

    gameclient:make_move(Abhishek, a1),
    timer:sleep(10),
    gameclient:make_move(Dharun, b2),
    timer:sleep(10),
    gameclient:make_move(Abhishek, a2),
    timer:sleep(10),    
    gameclient:make_move(Dharun, c3),
    timer:sleep(10),
    gameclient:make_move(Abhishek, a3).





test2(_Config)->



Abhijeet=gameclient:login("Abhijeet"),
Ranjan=gameclient:login("Ranjan"),


gameclient:new_game(Abhijeet),
    timer:sleep(10),

    gameclient:make_move(Abhijeet, a1),
    timer:sleep(10),
    gameclient:make_move(Ranjan, b2),
    timer:sleep(10),
    gameclient:make_move(Abhijeet, a2),
    timer:sleep(10),    
    gameclient:make_move(Ranjan, c3),
    timer:sleep(10),
    gameclient:make_move(Abhijeet, a3).
gameserver
模块中:

new_game(Name) ->
    global:send(?SERVER, { new_game, Name}).

make_move(Name, Move) ->
    global:send(?SERVER, { make_move, Name, Move }).

game_loop(Players, Games) ->
    process_flag(trap_exit, true),
    receive
        { new_game, Name} ->
            PlayerList=dict:fetch_keys(Players),
            PlayerAndOpponent=lists:partition(fun(A)->Name==A end, PlayerList),
            {_,OpponentNameList}=PlayerAndOpponent,
            OpponentName=list_to_tuple(OpponentNameList),
            case dict:find(Name, Players) of
                { ok, Pid } ->
                    case dict:find(element(1,OpponentName), Players) of
                        { ok, OpponentPid} ->
                            Pid ! { msg, "Ready to rumble against " ++ element(1,OpponentName) ++ "!" },
                            OpponentPid ! { msg, "Ready to rumble against " ++ Name ++ "!" },

                            GamePid = tictactoe:start({Pid, Name}, {OpponentPid, element(1,OpponentName)}),

                            GameKey = create_game_key(Name, element(1,OpponentName)),


                            link(GamePid),
                            game_loop(Players, dict:store(GameKey, GamePid, Games));
                        error ->
                            Pid ! { msg, "Did not find opponent " ++ OpponentName ++ "!" },
                            game_loop(Players, Games)
                    end;
                error ->
                    io:format("Could not find player ~p~n", [ Name ]),
                    game_loop(Players, Games)
            end;


        { make_move, Name, Move } ->
            PlayerList=dict:fetch_keys(Players),
            PlayerAndOpponent=lists:partition(fun(A)->Name==A end, PlayerList),
            {_,OpponentNameList}=PlayerAndOpponent,
            OpponentName=list_to_tuple(OpponentNameList),

            case dict:find(create_game_key(Name, element(1,OpponentName)), Games) of
                { ok, GamePid } ->

                    tictactoe:make_move(GamePid, Name, Move),
                    game_loop(Players, Games);
                error ->
                    game_loop(Players, Games)
            end

    end.
保留两个模块中的其余代码不变

但是现在当我运行模块时,我发现只有test1成功运行,而test2和test3没有成功运行我试图找到原因,我发现当test2和test3启动时,test1中的玩家名称仍然在dict中,但由于我在所有三个测试中都调用了
gameserver:start/0
,所以不应该发生这种情况

问题:

如果我必须为两个用户测试TictaToe游戏,但他们必须同时玩,那么我的测试用例模块应该是什么样子

编辑后 我研究了erlang的common_测试库,并在同一个问题上实现了它 通过创建一个新模块
testing2
,如下所示:

-module(testing).

%% ====================================================================
%% API functions
%% ====================================================================
-export([all/0]).



%% ====================================================================
%% Internal functions
%% ====================================================================
all()->

    test1(),
    timer:sleep(75),
    test2(),
    timer:sleep(75),
    test3(),
    timer:sleep(75).





test1()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test1 is ~p~n",
              [G_serv_Output1]),
    Abhishek=gameclient:login("Abhishek"),
    Dharun=gameclient:login("Dharun"),


    gameclient:new_game(Abhishek,"Dharun"),

    timer:sleep(5),

    gameclient:make_move(Abhishek,"Dharun", a1),
    timer:sleep(5),
    gameclient:make_move(Dharun,"Abhishek", b2),
    timer:sleep(5),
    gameclient:make_move(Abhishek,"Dharun", a2),
    timer:sleep(5), 
    gameclient:make_move(Dharun,"Abhishek", c3),
    timer:sleep(5),
    gameclient:make_move(Abhishek,"Dharun", a3).




test2()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test2 is ~p~n",
               [G_serv_Output1]),
    Abhijeet=gameclient:login("Abhijeet"),
    Ranjan=gameclient:login("Ranjan"),


    gameclient:new_game(Abhijeet,"Ranjan"),
    timer:sleep(5),

    gameclient:make_move(Abhijeet,"Ranjan", a1),
    timer:sleep(5),
    gameclient:make_move(Ranjan,"Abhijeet", b2),
    timer:sleep(5),
    gameclient:make_move(Abhijeet,"Ranjan", a2),
    timer:sleep(5), 
    gameclient:make_move(Ranjan,"Abhijeet", c3),
    timer:sleep(5),
    gameclient:make_move(Abhijeet,"Ranjan", a3).





test3()->

    G_serv_Output1=gameserver:start(),
    io:format("Value of G_serv_Output in test3 is ~p~n",
              [G_serv_Output1]),
    Bana=gameclient:login("Bana"),
    Sagar=gameclient:login("Sagar"),


    gameclient:new_game(Bana,"Sagar"),
    timer:sleep(5),

    gameclient:make_move(Bana,"Sagar", a1),
    timer:sleep(5),
    gameclient:make_move(Sagar,"Bana", b2),
    timer:sleep(5),
    gameclient:make_move(Bana,"Sagar", a2),
    timer:sleep(5), 
    gameclient:make_move(Sagar,"Bana", c3),
    timer:sleep(5),
    gameclient:make_move(Bana,"Sagar", a3).
new_game(Pid) ->
    Pid ! {new_game}.

make_move(Pid, Move) -> 

    Pid ! { make_move, Move }.
loop(Name) ->
    receive
        { new_game} ->
            gameserver:new_game(Name),
            loop(Name);
        { make_move, Move } ->
            gameserver:make_move(Name, Move),
            loop(Name)

    end.
-module(testing2).
-include_lib("common_test/include/ct.hrl").
%% ====================================================================
%% API functions
%% ====================================================================
-export([all/0, groups/0, init_per_group/2, end_per_group/2]).
-export([test1/1,test2/1]).



%% ====================================================================
%% Internal functions
%% ====================================================================
all() -> [{group, session}].

groups() -> [{session,
              [],
              [{group, clients}]},
             {clients,
              [parallel, {repeat, 1}],
              [test1, test2]}].

init_per_group(session, Config) ->
   gameserver:start(),
    Config;
init_per_group(_, Config) ->
    Config.

end_per_group(session, _Config) ->
    gameserver:stop();
end_per_group(_, _Config) ->
    ok.

test1(_Config)->



Abhishek=gameclient:login("Abhishek"),
Dharun=gameclient:login("Dharun"),


gameclient:new_game(Abhishek),

    timer:sleep(10),

    gameclient:make_move(Abhishek, a1),
    timer:sleep(10),
    gameclient:make_move(Dharun, b2),
    timer:sleep(10),
    gameclient:make_move(Abhishek, a2),
    timer:sleep(10),    
    gameclient:make_move(Dharun, c3),
    timer:sleep(10),
    gameclient:make_move(Abhishek, a3).





test2(_Config)->



Abhijeet=gameclient:login("Abhijeet"),
Ranjan=gameclient:login("Ranjan"),


gameclient:new_game(Abhijeet),
    timer:sleep(10),

    gameclient:make_move(Abhijeet, a1),
    timer:sleep(10),
    gameclient:make_move(Ranjan, b2),
    timer:sleep(10),
    gameclient:make_move(Abhijeet, a2),
    timer:sleep(10),    
    gameclient:make_move(Ranjan, c3),
    timer:sleep(10),
    gameclient:make_move(Abhijeet, a3).
但是当我看到ct生成的html日志时,我仍然看不到这些游戏正在运行,而是看到了以下内容 在测试1中

=== Started at 2017-09-19 11:48:08



"Welcome to tictactoe server!"

"Welcome to tictactoe server!"

"Ready to rumble against Abhishek!"

"Ready to rumble against Dharun!"




=== Ended at 2017-09-19 11:48:08
=== successfully completed test case
=== Returned value: {make_move,a3}
和在测试2中

=== Started at 2017-09-19 11:48:08



"Welcome to tictactoe server!"

"Welcome to tictactoe server!"

"Ready to rumble against Ranjan!"

"Ready to rumble against Abhijeet!"

"It is not your turn yet!"

"It is not your turn yet!"




=== Ended at 2017-09-19 11:48:08
=== successfully completed test case
=== Returned value: {make_move,a3}

请帮帮我。

我对测试的要求非常严格。你可以有意义地测试纯功能,也可以有意义地对集成系统进行外部测试,但在这两者之间,是一堆模糊的疯狂,似乎没有人能比现实世界中的用户测试更好地处理(尽管许多宗教和意识形态都是围绕这一点出现的)。也就是说,我相信最好的利用时间的方法是先了解基于属性的测试,然后再了解基于属性的测试。其他测试方法和框架可以等待。@zxq9感谢您的链接。那么这是否意味着项目(这个游戏)是如何进行的呢当多个用户在玩时,它的行为只有在现实世界中有多对人在玩时才能被检查。我们不能通过编写一个或两个模块来检查它吗?不幸的是,并发性并没有那么简单。在进程之间编写的所有内容最多都具有部分事件顺序。因此,系统状态是不可证明的。Erlang的“让它崩溃”和严格的进程隔离是针对管理这一难题而设计的。并发系统极其微妙和复杂,因此当我们遇到意外情况时,我们会崩溃。你的测试模型只会和你的分析一样可靠(你会错过一些东西)。如果您考虑将其用于测试,那么您已经编写了模块来处理它。例外是纯函数。实际上我对erlang是新手,我的目标是了解erlang中的测试是如何进行的。因此,如果我有一些用erlang编写的项目,1)我应该只在单元方面检查它。2) 那么,我如何才能真正测试该项目的并发性呢?@abhishekranjan您提供了一个指向代码的链接,这很好,但如果您在那里有一个分支,并对问题中所述的更改,那就更好了。这样可以更容易地找到代码中不起作用的地方。我对测试的态度非常严格。你可以有意义地测试纯功能,也可以有意义地对集成系统进行外部测试,但在这两者之间,是一堆模糊的疯狂,似乎没有人能比现实世界中的用户测试更好地处理(尽管许多宗教和意识形态都是围绕这一点出现的)。也就是说,我相信最好的利用时间的方法是先了解基于属性的测试,然后再了解基于属性的测试。其他测试方法和框架可以等待。@zxq9感谢您的链接。那么这是否意味着项目(这个游戏)是如何进行的呢当多个用户在玩时,它的行为只有在现实世界中有多对人在玩时才能被检查。我们不能通过编写一个或两个模块来检查它吗?不幸的是,并发性并没有那么简单。在进程之间编写的所有内容最多都具有部分事件顺序。因此,系统状态是不可证明的。Erlang的“让它崩溃”和严格的进程隔离是针对管理这一难题而设计的。并发系统极其微妙和复杂,因此当我们遇到意外情况时,我们会崩溃。你的测试模型只会和你的分析一样可靠(你会错过一些东西)。如果您考虑将其用于测试,那么您已经编写了模块来处理它。例外是纯函数。实际上我对erlang是新手,我的目标是了解erlang中的测试是如何进行的。因此,如果我有一些用erlang编写的项目,1)我应该只在单元方面检查它。2) 那么,我如何才能真正测试该项目的并发性呢?@abhishekranjan您提供了一个指向代码的链接,这很好,但如果您在那里有一个分支,并对问题中所述的更改,那就更好了。这样可以更容易地找到代码中不起作用的内容。