Erlang YAWS: How to test a simple REST web service?
Asked Answered
O

3

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?

Orellana answered 21/8, 2012 at 17:45 Comment(0)
S
6

Did you try etest and especially etest_http?

Staggard answered 21/8, 2012 at 22:47 Comment(0)
M
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

Millionaire answered 22/8, 2012 at 8:59 Comment(0)
P
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
Pronounced answered 22/8, 2012 at 6:9 Comment(5)
I do not need to test massive system loads with many requests. Will ibrowse be enough to run from the same machine?Orellana
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?Orellana
I would gladly mark your answer as accepted if you update it with information on how to properly embed ibrowse into an Erlang application.Orellana
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)Orellana
yes. Have it in the code path, just like mnesia and stdlib. it's ebin should be in erlang lib.Pronounced

© 2022 - 2024 — McMap. All rights reserved.