diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b755a3bbb702035b1f080fbf90c0fca675ce50d..f042910451c313f6ae813a886c498860dbaf24cb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,4 @@ before_script: - - banner "Environment" - - env | sort - - docker info - git config --global url.https://.insteadOf git:// - mkdir -p ~/.hex ~/.config/rebar3 - printf "{key,<<\"$HEX_KEY\">>}.\n{username,<<\"$HEX_USERNAME\">>}.\n" > ~/.hex/hex.config @@ -18,14 +15,12 @@ stages: compile: stage: compile script: - - banner "compile" - rebar3 as production do compile test: stage: test script: - - banner "test" - - rebar3 as test do eunit --cover --dir=test, cover --verbose + - rebar3 as test do eunit --cover --dir=test, cover --verbose, dialyzer - coverage.escript _build/test/cover/eunit.coverdata publish: @@ -33,6 +28,5 @@ publish: only: - /^\d+[.]\d+[.]\d+$/ # Only publish HEAD tagged with semantic version script: - - banner "publish" - rebar3 update - echo Y | rebar3 hex publish diff --git a/Makefile b/Makefile index 33df7b3a83084b823251b754ca2d2070c488fbf1..843e42fd0797895486db4b12a4c8035c968d1032 100644 --- a/Makefile +++ b/Makefile @@ -6,21 +6,21 @@ REBAR := $(CURDIR)/rebar3 $(shell if ! [ -e "$(REBAR)" ]; then curl -jksSL -o $(REBAR) https://s3.amazonaws.com/rebar3/rebar3; chmod +x $(REBAR); fi) endif -all: tests +all: eunit compile: @$(REBAR) compile -tests: +eunit: @$(REBAR) do eunit --cover --dir=test, cover --verbose -analyze: +dialyzer: @$(REBAR) dialyzer release: @$(REBAR) release -docs: +edoc: @$(REBAR) edoc clean: diff --git a/include/gurka.hrl b/include/gurka.hrl index 601b8b61b524cc8b5afbadcc2922cac75132b1ba..8c2abddc86832cf9384021c5f5acca33e64015db 100644 --- a/include/gurka.hrl +++ b/include/gurka.hrl @@ -1,10 +1,3 @@ --type phase() :: feature | background | scenario | scenario_outline | meta. --type action() :: skip | start | 'end' | desc | title | given | 'when' | then | examples | headers | values | tags | table | docstring. --type tokens() :: [tokens() | binary() | {table, any()} | {docstring, any()}]. --type row() :: integer(). --type meta() :: [{atom(),term()}]. --type lines() :: [{row(), binary(), tokens()}]. - -record(step, { phase :: phase(), action = [] :: action(), @@ -13,4 +6,11 @@ meta = [] :: meta() }). +-type phase() :: feature | background | scenario | scenario_outline | meta. +-type action() :: skip | start | 'end' | desc | title | given | 'when' | then | examples | headers | values | tags | table | docstring. +-type tokens() :: [tokens() | binary() | {table, any()} | {docstring, any()}]. +-type row() :: integer(). +-type meta() :: [{atom(),term()}]. +-type lines() :: [{row(), binary(), tokens()}]. -type feature() :: [#step{}]. +-type result() :: [{ok | error | term(), #step{}} | result()]. diff --git a/rebar.config b/rebar.config index 8d42c8a06c75e0f08fb86ab6a8306f6bccae391c..32b92d895021b67fd30de98fcf1b889f90f6545f 100644 --- a/rebar.config +++ b/rebar.config @@ -5,6 +5,11 @@ {extended_start_script, true} ]}. +{edoc_opts, [ + {preprocess, true}, + {includes, ["include"]} +]}. + {profiles, [ {test, [ {eunit_opts, [{report, {eunit_surefire, [{dir, "_build/test"}]}}]}, diff --git a/src/gurka.erl b/src/gurka.erl index 4cf0e024b1d04799b47e93417b365bdb3e20cf6f..120c3f2d99e45fdd2e3b7a640d92d0a0fcf6c78f 100644 --- a/src/gurka.erl +++ b/src/gurka.erl @@ -4,13 +4,28 @@ -export([run/1, run/2, run/3]). +-spec run(File) -> {ok, Result} | {fail, Result} | {error, Reason} when + File :: file:name_all(), + Result :: result(), + Reason :: file:posix() | badarg | terminated | system_limit. run(File) -> run(File, []). +-spec run(File, Options) -> {ok, Result} | {fail, Result} | {error, Reason} when + File :: file:name_all(), + Options :: [term()], + Result :: result(), + Reason :: file:posix() | badarg | terminated | system_limit. run(File, Options) -> Module = list_to_atom("feature_" ++ filename:basename(File, ".feature")), run(File, Module, Options). +-spec run(File, Module, Options) -> {ok, Result} | {fail, Result} | {error, Reason} when + File :: file:name_all(), + Module :: module(), + Options :: [term()], + Result :: result(), + Reason :: file:posix() | badarg | terminated | system_limit. run(File, Module, Options) -> case gurka_parser:parse(File) of {ok, Feature} -> diff --git a/src/gurka_eunit.erl b/src/gurka_eunit.erl index 0b405d4cf1cceb7e536e4847a995635da86e3574..d40ff5f1f72918882569acb42327617a5a02c55a 100644 --- a/src/gurka_eunit.erl +++ b/src/gurka_eunit.erl @@ -4,12 +4,23 @@ -export([setup/1, setup/2, setup/3]). +-type eunit_fixture() :: {setup, spawn, Setup::fun(), Cleanup::fun(), Tests::fun()}. + +-spec setup(Setup) -> eunit_fixture() when + Setup :: fun(). setup(Setup) -> setup(Setup, fun(_) -> ok end). +-spec setup(Setup, Cleanup) -> eunit_fixture() when + Setup :: fun(), + Cleanup :: fun(). setup(Setup, Cleanup) -> setup(Setup, Cleanup, fun(Message) -> io:fwrite(user, "~s~n", [Message]) end). +-spec setup(Setup, Cleanup, Log) -> eunit_fixture() when + Setup :: [file:name_all()] | fun(), + Cleanup :: fun(), + Log :: fun(). setup(Features, Cleanup, Log) when is_list(Features) -> setup(fun() -> Features end, Cleanup, Log); @@ -25,12 +36,12 @@ feature(Log, File) -> Tags = parse_tags(), Formatter = parse_format(), Options = [{file, File}, {tags, Tags}, {formatter, Formatter}, {log, Log}], - Result = gurka:run(File, Options), - Log(io_lib:format("~s", [Formatter:format(Result, Options)])), - case Result of - {ok, _} -> + {Status, Result} = gurka:run(File, Options), + Log(io_lib:format("~s", [Formatter:format(Status, Result, Options)])), + case Status of + ok -> ok; - {fail, _} -> + fail -> erlang:error({failed, File}) end. @@ -63,4 +74,4 @@ list_to_number(L) -> catch error:badarg -> list_to_integer(L) - end. \ No newline at end of file + end. diff --git a/src/gurka_formatter_compact.erl b/src/gurka_formatter_compact.erl index 8e419ee6d5094735dd3741b5684919b51d204250..fb1b15dd785b0d9c125b4de7b2e41b666bb9551b 100644 --- a/src/gurka_formatter_compact.erl +++ b/src/gurka_formatter_compact.erl @@ -2,9 +2,13 @@ -include("gurka.hrl"). --export([format/2]). +-export([format/3]). -format({Status, Result}, Opts) -> +-spec format(Status, Result, Opts) -> io_lib:chars() when + Status :: ok | fail | error, + Result :: result() | file:posix() | badarg | terminated | system_limit, + Opts :: [term()]. +format(Status, Result, Opts) -> case proplists:get_value(file, Opts) of undefined -> format_steps(Result); diff --git a/src/gurka_formatter_plain.erl b/src/gurka_formatter_plain.erl index c24d8b655e883fa527a52ea8178610410bd8d7c5..8b8977d34ffb5361b4ad86be3b6c5f34c71c8539 100644 --- a/src/gurka_formatter_plain.erl +++ b/src/gurka_formatter_plain.erl @@ -2,9 +2,13 @@ -include("gurka.hrl"). --export([format/2]). +-export([format/3]). -format({Status, Result}, Opts) -> +-spec format(Status, Result, Opts) -> io_lib:chars() when + Status :: ok | fail | error, + Result :: result() | file:posix() | badarg | terminated | system_limit, + Opts :: [term()]. +format(Status, Result, Opts) -> format_header(Status, Opts) ++ format_steps(Result, undefined). format_header(Status, Opts) -> diff --git a/src/gurka_parser.erl b/src/gurka_parser.erl index ff876a2dfb8eb9c254d3d398419e25f4090c4d8c..abfab8d020336634bbd81c360bcb4ad947264c8f 100644 --- a/src/gurka_parser.erl +++ b/src/gurka_parser.erl @@ -5,7 +5,7 @@ -export([parse/1, tokens/1]). -spec parse(File) -> {ok, Feature} | {error, Reason} when - File :: file:name(), + File :: file:name_all(), Feature :: feature(), Reason :: file:posix() | badarg | terminated | system_limit. parse(File) -> @@ -125,6 +125,8 @@ build_docstring([{_Row, Line, _Tokens} | Lines], Docstring) -> normalize_token(Token) -> hd(string:tokens(string:to_lower(binary_to_list(Token)), ":")). +-spec tokens(Line) -> [binary()] when + Line :: binary(). tokens(Line) -> [strip_quotes(Token) || Token <- tokens(Line, [], <<>>)]. diff --git a/src/gurka_transform.erl b/src/gurka_transform.erl index 48c585cb9f68657d3763d94324adede1d56618ad..de91ac676ddeac8a849496824976e185e1b7a7e3 100644 --- a/src/gurka_transform.erl +++ b/src/gurka_transform.erl @@ -1,6 +1,7 @@ -module(gurka_transform). -export([parse_transform/2]). +%% @private parse_transform(Forms, _Options) -> forms(Forms).