7

In a simple Erlang YAWS-based RESTful application I would like to have a set of tests that send HTTP requests to a RESTful API, get responses from the server and then test those responses.

It would be nice if each "send-request-get-request-test" test could be run from within EUnit (making possible to use test generators).

I would also like to be able to run this set of tests with rebar (make test).

Recently I used ibrowse in another application (Mochiweb), but I found it quiet cumbersome to use.

Are there any other options to write Erlang/OTP tests that can send HTTP requests to a YAWS RESTful application? What is the most common way to do that?

Community
  • 1
  • 1
skanatek
  • 5,133
  • 3
  • 47
  • 75

3 Answers3

6

Did you try etest and especially etest_http?

Tilman
  • 2,015
  • 14
  • 16
5

I use common_test with ibrowse for testing REST based services.

  1. It's part of erlang distribution
  2. You can call the tests from rebar
  3. You can configure your tests, so the run in parallel, sequencies ....

Have a look at this presentation : http://www.erlang-factory.com/upload/presentations/275/CommonTestPresentation.pdf

Ulf
  • 96
  • 5
4

You could use Tsung, but this is what i would do: I would write a massively threaded tester using a good HTTP Client like curl, or ibrowse running from a different machine. and then test depending on what i want.

EDIT


Now, have the ibrowse library in the erlang lib, re-compiled and having its ebin in the code path.
%% To ensure that Ibrowse is started
ensure_ibrowse()-> case whereis(ibrowse) of undefined -> ibrowse:start(); Any when is_pid(Any)-> ok end.
%% To make a get request
do_get(Link)-> try ibrowse:send_req(Link,[],get) of {ok,_,_,Result} -> %% Result could be JSON in which case you would %% mochijson2:decode(Result) Other -> {error,Other} catch E1:E2 -> {exception,{E1,E2}} end.
%% To save response to a file
save_to_file(Link)-> try ibrowse:send_req(Link,[],get,[],[{save_response_to_file,true}]) of {ok,_,_,{file,FilePath}} -> %% Do anything with the file, %% ------------------------------------------------------- %% like {ok,FileHandle} = file:open(FilePath,[read]) %% ----------------------------------------------------- %% OR {ok,Contents} = file:read_file(FilePath) %% ------------------------------------------------------- %% OR if the response is a .zip file %% {ok,FileList} = zip:unzip(FilePath), %% [begin process_file_contents(element(2,file:read_file(F))) end || F <- FileList] %% --------------------------------------------------------------------------------
Other -> {error,Other} catch E1:E2 -> {exception,{E1,E2}} end.
%% To make a POST %% Usually, if you use mochijson to encode erlang terms %% to JSON, you will:: %% JSON = lists:flatten(mochijson:encode({struct,[Terms]}))
post(Link,JSON) -> try ibrowse:send_req(Link,[],post,JSON,[]) of {_,_,_,Result} -> try mochijson2:decode(Result) of {struct,[{<<"key1">>,<<"value1">>},...]} ->
%% proceed here JSONOther -> {error,JSONOther} catch R:R2 -> {exception,{R:R2}} end; Any -> erlang:throw({write_failed,Link,Any}) catch E1:E2 -> {exception,{E1,E2}} end.
%% To make a put request %% same as Post, just change the atom 'post' to 'put'

%% To add headers to a request
post(Link,JSON)-> Headers = [{"Content-Type","application/json"}], try ibrowse:send_req(Link,Headers,post,JSON,[]) of
{_,_,_,Result} -> try mochijson2:decode(Result) of {struct,[{<<"key1">>,<<"value1">>},...]} ->
%% proceed here JSONOther -> {error,JSONOther} catch R:R2 -> {exception,{R:R2}} end; Any -> erlang:throw({write_failed,Link,Any}) catch E1:E2 -> {exception,{E1,E2}} end.
Let us know, if you fail to install ibrowse in your code path
Muzaaya Joshua
  • 7,736
  • 3
  • 47
  • 86
  • I do not need to test massive system loads with many requests. Will ibrowse be enough to run from the same machine? – skanatek Aug 22 '12 at 07:06
  • And if I use ibrowse, how can I incorporate it into the EUnit suite of my OTP application? Should I put the ibrowse application into the deps/ directory and call ibrowse:send_req() from my EUnit tests? – skanatek Aug 22 '12 at 08:14
  • I would gladly mark your answer as accepted if you update it with information on how to properly embed ibrowse into an Erlang application. – skanatek Aug 22 '12 at 12:40
  • Muzaaya Joshua, thanks! I have put the ibrowse dir into the deps/ dir of my Mochiweb application. The tests that involve using some C code which is stored in ebin/ give an error, because they cannot find the C binaries (C binaries are in ebin/, but ibrowse beam files are in deps/ibrowse/ebin). And what did you mean by saying "have the ibrowse library in the erlang lib, ... having its ebin in the code path"? (sorry for such a noob question) – skanatek Sep 02 '12 at 08:16
  • yes. Have it in the code path, just like `mnesia` and `stdlib`. it's `ebin` should be in `erlang lib`. – Muzaaya Joshua Sep 03 '12 at 10:33