Commits

emmi...@a5195066-8e3e-0410-a82a-05b01b1b9875  committed dbd02f6

* Run functional tests from "make test"
* Clean up the output from all test suites
* New README file
* Remove create_parser stuff because "make" handles this
* Make erlydtl:compile/2,3 a wrapper for erlydtl_compiler:compile/2,3

  • Participants
  • Parent commits 6c843e0
  • Tags 0.5.0

Comments (0)

Files changed (6)

 
 test:
 	$(ERL) -noshell -pa ebin \
+		-s erlydtl_functional_tests run_tests \
+		-s erlydtl_dateformat_tests run_tests \
 		-s erlydtl_unittests run_tests \
-		-s erlydtl_dateformat_tests run_tests \
 		-s init stop
 	
 clean:
+ErlyDTL
+=======
+
+ErlyDTL implements most but not all of the Django Template Language.
+
+Project homepage: http://code.google.com/p/erlydtl/
+
+
+Compilation
+-----------
+
+To compile ErlyDTL, type "make" in this directory.
+
+
+Template compilation
+--------------------
+
+Four ways:
+
+    erlydtl:compile("/path/to/template.dtl", my_module_name)
+
+    erlydtl:compile("/path/to/template.dtl", my_module_name, Options)
+
+    erlydtl:compile(<<"<html>{{ foo }}</html>">>, my_module_name)
+
+    erlydtl:compile(<<"<html>{{ foo }}</html>">>, my_module_name, Options)
+
+Options is a proplist possibly containing:
+
+    doc_root - Included template paths will be relative to this directory;
+        defaults to the compiled template's directory.
+
+    custom_tags_dir - Directory of DTL files (no extension) includable as tags.
+        E.g. if $custom_tags_dir/foo contains "<b>{{ bar }}</b>", then 
+        "{{ foo bar=100 }}" will evaluate to "<b>100</b>". Get it?
+
+    vars - Variables (and their values) to evaluate at compile-time rather than
+        render-time. 
+
+    reader - {module, function} tuple that takes a path to a template and returns
+        a binary with the file contents. Defaults to {file, read_file}. Useful
+        for reading templates from a network resource.
+
+    compiler_options - Proplist passed directly to compiler:forms/2 
+
+    force_recompile - Recompile the module even if the source's checksum has not
+        changed. Useful for debugging.
+
+
+Usage (of a compiled template)
+------------------------------ 
+
+    my_compiled_template:render(Variables) -> {ok, IOList} | {error, Err}
+
+        Variables is a proplist, dict, gb_tree, or a parameterized module
+        (whose method names correspond to variable names). The variable 
+        values can be atoms, strings, binaries, or (nested) variables.
+
+        IOList is the rendered template.
+
+    my_compiled_template:source() -> {FileName, CheckSum}
+
+        Name and checksum of the original template file.
+
+    my_compiled_template:dependencies() -> [{FileName, CheckSum}]
+
+        List of names/checksums of templates included by the original template
+        file. Useful for frameworks that recompile a template only when the
+        template's dependencies change.
+
+
+Tests
+-----
+
+From a Unix shell, run:
+
+    make test
+
+Note that the tests will create some output in examples/rendered_output.

File src/erlydtl/erlydtl.erl

 %%% @author    Evan Miller <emmiller@gmail.com>
 %%% @copyright 2008 Roberto Saccon, Evan Miller
 %%% @doc  
-%%% Helper module to start and stop ErlyDTL application and for 
-%%% creating yecc-grammar based template parser
+%%% Public interface for ErlyDTL
 %%% @end  
 %%%
 %%% The MIT License
 -author('emmiller@gmail.com').
 
 %% API
--export([create_parser/0, parser_src/0]).
+-export([compile/2, compile/3]).
 
-%% --------------------------------------------------------------------
-%% Definitions
-%% --------------------------------------------------------------------
--define(PRINT_ERR_WARNS, [report_warnings, report_errors]). 
+compile(FileOrBinary, Module) ->
+    erlydtl_compiler:compile(FileOrBinary, Module).
 
-    
-%%--------------------------------------------------------------------
-%% @spec () ->  Ok::atom() | Err::tuple()
-%% @doc creates the yecc-based ErlyDTL parser
-%% @end 
-%%--------------------------------------------------------------------
-create_parser() ->
-    create_parser("src/erlydtl/erlydtl_parser", "ebin").
-
- 
-%%--------------------------------------------------------------------
-%% @spec () -> string()
-%% @doc creates the yecc-based ErlyDTL parser
-%% @end 
-%%--------------------------------------------------------------------   
-parser_src() ->
-    {file, Ebin} = code:is_loaded(?MODULE),
-    filename:join([filename:dirname(filename:dirname(Ebin)), 
-        "src", "erlydtl", "erlydtl_parser.yrl"]).
-    
-         
-%%====================================================================
-%% Internal functions
-%%====================================================================
-
-create_parser(Path, Outdir) ->
-    case yecc:file(Path) of
-        {ok, _} ->
-            compile_parser(Path, Outdir);
-        _ ->
-            {error, "yecc parser generation failed"}
-    end.
-
-
-compile_parser(Path, Outdir) ->
-    case compile:file(Path, ?PRINT_ERR_WARNS ++ [{outdir, Outdir}]) of
-        {ok, Bin} ->
-            code:purge(Bin),
-            case code:load_file(Bin) of
-                {module, _} ->
-                    ok;
-                _ ->
-                    {error, "yecc parser reload failed"}
-            end;
-        _ ->
-            {error, "yecc parser compilation failed"}
-    end.
+compile(FileOrBinary, Module, Options) ->
+    erlydtl_compiler:compile(FileOrBinary, Module, Options).

File src/tests/erlydtl_dateformat_tests.erl

 -define(DISPLAY_PASSES, false).
 
 run_tests() ->
-   test_group_runner([
+   io:format("Running date format tests...~n"),
+   Failures = test_group_runner([
       {
          "date 1",
          {1979, 7, 8}, % just a date
       { "Ordinal suffix 22", {1984,1,121}, [{"S", "st"}] }
    ]),
 
+   io:format("Date format failures: ~p~n~n", [Failures]),
+
    ok.
 
-test_group_runner([]) -> ok;
+test_group_runner([]) -> 0;
 test_group_runner([{Info, DateParam, Tests} | Rest]) ->
-   io:format("Running ~p -> ", [Info]),
+   io:format(" Test ~p -> ", [Info]),
    PassCount = test_runner(DateParam, Tests),
    case PassCount =:= length(Tests) of
        true ->
        _ ->
            io:format("~nFailed ~p/~p~n", [length(Tests) - PassCount, length(Tests)])
    end,
-   test_group_runner(Rest).
+   test_group_runner(Rest) + length(Tests) - PassCount.
 
 test_runner(DateParam, Tests) ->
     test_runner(DateParam, Tests, 1, 0).
 is(_TestNum, _Text, Input1, Input2) when Input1 =:= Input2 ->
     1;
 is(TestNum, Text, Input1, Input2) -> 
-    io:format("~nnot ok ~p - ~s~n     got : ~p~n expcted : ~p", [
+    io:format("~nnot ok ~p - ~s~n     got : ~p~n expected : ~p", [
        TestNum, Text, Input1, Input2]),
     0.

File src/tests/erlydtl_functional_tests.erl

     
 
 run_tests() ->    
-    case maybe_create_parser() of
-        ok ->
-            case fold_tests() of
-                {N, []}->
-                    Msg = lists:concat(["All ", N, " functional tests passed"]),
-                    {ok, Msg};
-                {_, Errs} ->
-                    io:format("Errors: ~p~n",[Errs]),
-                    failed
-            end;
-        Err ->
-            Err
+    io:format("Running functional tests...~n"),
+    case fold_tests() of
+        {N, []}->
+            Msg = lists:concat(["All ", N, " functional tests passed~n~n"]),
+            io:format(Msg),
+            {ok, Msg};
+        {_, Errs} ->
+            io:format("Errors: ~p~n~n",[Errs]),
+            failed
     end.
 
 
 run_test(Name) ->
-    case maybe_create_parser() of
-        ok ->
-            test_compile_render(filename:join([templates_docroot(), Name]));
-        Err ->
-            Err
-    end.    
+    test_compile_render(filename:join([templates_docroot(), Name])).
 
 
 %%====================================================================
 %% Internal functions
 %%====================================================================
 
-maybe_create_parser() ->
-    case filelib:is_regular(erlydtl:parser_src()) of
-        ok ->
-            ok; 
-        _ ->
-            erlydtl:create_parser()   
-    end.
-
-
 fold_tests() ->
     filelib:fold_files(templates_docroot(), "^[^\.].+", false,
         fun
             Options = [
                 {vars, CompileVars}, 
                 {force_recompile, true}],
-            io:format("Template: ~p, ... compiling ... ", [Name]),
-            case erlydtl_compiler:compile(File, Module, Options) of
+            io:format(" Template: ~p, ... compiling ... ", [Name]),
+            case erlydtl:compile(File, Module, Options) of
                 ok ->
                     case CompileStatus of
                         ok -> test_render(File, list_to_atom(Module), RenderStatus, RenderVars);

File src/tests/erlydtl_unittests.erl

     ].
 
 run_tests() ->
+    io:format("Running unit tests...~n"),
     Failures = lists:foldl(
         fun({Group, Assertions}, GroupAcc) ->
-                io:format("Running test group ~p...~n", [Group]),
+                io:format(" Test group ~p...~n", [Group]),
                 lists:foldl(fun({Name, DTL, Vars, Output}, Acc) ->
-                            case erlydtl_compiler:compile(DTL, erlydtl_running_test, []) of
+                            case erlydtl:compile(DTL, erlydtl_running_test, []) of
                                 {ok, _} ->
                                     {ok, IOList} = erlydtl_running_test:render(Vars),
                                     {ok, IOListBin} = erlydtl_running_test:render(vars_to_binary(Vars)),
                     end, GroupAcc, Assertions)
         end, [], tests()),
     
-    io:format("Failures: ~p~n", [Failures]),
-    erlang:halt().
+    io:format("Unit test failures: ~p~n", [Failures]).
 
 vars_to_binary(Vars) when is_list(Vars) ->
     lists:map(fun