Repository: jeremyjh/dialyxir (elixir)

Issue:
Passing command line arguments does not work
Version 0.5.0

```elixir
  def project do
    [
      ...
      dialyzer: [
        plt_add_deps: :transitive,
        ignore_warnings: "dialyzer.ignore-warnings",
        flags: ["--quiet"]
      ]
    ]
  end
```

Running:

```shell
mix dialyzer
Compiling 23 files (.ex)
Generated efrontback app
Checking PLT...
[skipped]
PLT is up to date!
Starting Dialyzer
dialyzer args: [check_plt: false,
 init_plt: 'skipped',
 files_rec: ['skipped'],
 warnings: [:quiet, :unknown]]
:dialyzer.run error: Unknown dialyzer warning option: quiet
```

The docs say: _You can specify any `dialyzer` command line argument with the :flags keyword._

Am I missing anything?


Pull request:
Support a "Quiet" Option
This will resolve #85 .

Also resolves #111. 

Patch:
diff --git a/.formatter.exs b/.formatter.exs
index 20a8291..a84a9b5 100644
--- a/.formatter.exs
+++ b/.formatter.exs
@@ -1,10 +1,5 @@
 [
   inputs: [
-    "lib/dialyxir/formatter.ex",
-    "lib/dialyxir/pretty_print.ex",
-    "lib/dialyxir/project.ex",
-    "lib/dialyxir/warning.ex",
-    "lib/dialyxir/warning_helpers.ex",
-    "lib/dialyxir/warnings/*.ex"
-  ]
+    "*.exs", "lib/**/*.{ex,exs}", "test/**/*.{ex,exs}",
+  ],
 ]
diff --git a/.travis.yml b/.travis.yml
index 4249c0e..b2a706e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,9 @@ otp_release:
 script:
   - mix test --trace
   - MIX_ENV=prod mix do compile --warnings-as-errors, archive.build, archive.install --force
+  - mix format --check-formatted
   - MIX_ENV=prod mix dialyzer --halt-exit-status
+  - OUTPUT_TESTS=true mix test
 branches:
   except:
     - /^[0-9]\.[0-9]/
diff --git a/LICENSE b/LICENSE
index 86fa86e..10078d6 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2013-2015 Jeremy Huffman. 
+Copyright 2013-2018 Jeremy Huffman and contributors.
 
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index da52c17..924fa8e 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,13 @@ Mix tasks to simplify use of Dialyzer in Elixir projects.
 
 [![Build Status](https://travis-ci.org/jeremyjh/dialyxir.svg?branch=master)](https://travis-ci.org/jeremyjh/dialyxir)
 
+## Changes in 1.0
+
+Elixir 1.6 is required, to support the new pretty printing feature. If your
+project is not yet on 1.6, continue to specify 0.5 in your mix deps.
+
+Warning messages have been greatly improved, but are filtered through the legacy formatter to support your existing ignore files. You can optionally use the new Elixir [term format](#elixir-term-format) for ignore files. You may want to use the `--format short` argument in your CI pipelines. There are several formats, also there is a new `explain` feature - for details see CLI [options](#command-line-options).
+
 ## Changes in 0.4 and 0.5
 
 If you've been using earlier versions of Dialyxir there are some changes you may need to make in the configuration of your existing projects. A summary of the most common issues and changes are found in the Wiki pages for [0.4](https://github.com/jeremyjh/dialyxir/wiki/Upgrading-to-0.4) and [0.5](https://github.com/jeremyjh/dialyxir/wiki/Upgrading-to-0.5).
@@ -53,16 +60,17 @@ mix dialyzer
 
 ### Command line options
 
-  * `--no-compile`       - do not compile even if needed.
-  * `--no-check`         - do not perform (quick) check to see if PLT needs updated.
-  * `--halt-exit-status` - exit immediately with same exit status as dialyzer.
+  * `--no-compile`         - do not compile even if needed.
+  * `--no-check`           - do not perform (quick) check to see if PLT needs updated.
+  * `--halt-exit-status`   - exit immediately with same exit status as dialyzer.
     useful for CI. do not use with `mix do`.
-  * `--plt`              - only build the required plt(s) and exit.
+  * `--plt`                - only build the required plt(s) and exit.
   *  `--format short`      - format the warnings in a compact format.
   *  `--format raw`        - format the warnings in format returned before Dialyzer formatting
   *  `--format dialyxir`   - format the warnings in a pretty printed format
   *  `--format dialyzer`   - format the warnings in the original Dialyzer format
   *  `--explain warning`   - explain the class of warnings, e.g. no_return
+  *  `--quiet`             - suppress all informational messages
 
 Warning flags passed to this task are passed on to `:dialyzer`.
 
@@ -201,7 +209,9 @@ config.ex:64: The call ets:insert('Elixir.MyApp.Config',{'Elixir.MyApp.Config',_
 done (warnings were emitted)
 ```
 
-Dialyzer also recognizes an Elixir format of the ignore file. If your ignore file is a `exs` file, Dialyxir will evaluate it and process its data structure. The file looks like the following:
+### Elixir Term Format
+
+Dialyzer also recognizes an Elixir format of the ignore file. If your ignore file is an `exs` file, Dialyxir will evaluate it and process its data structure. The file looks like the following:
 
 ```elixir
 [
diff --git a/lib/dialyxir.ex b/lib/dialyxir.ex
new file mode 100644
index 0000000..61bbdf9
--- /dev/null
+++ b/lib/dialyxir.ex
@@ -0,0 +1,18 @@
+defmodule Dialyxir do
+  @moduledoc false
+  use Application
+  alias Dialyxir.Output
+
+  def start(_, _) do
+    Output.info("""
+      Warning: the `dialyxir` application's start function was called, which likely means you
+      did not add the dependency with the `runtime: false` flag. This is not recommended because
+      it will mean that unnecessary applications are started, and unnecessary applications are most
+      likely being added to your PLT file, increasing build time.
+      Please add `runtime: false` in your `mix.exs` dependency section e.g.:
+      {:dialyxir, "~> 0.5", only: [:dev], runtime: false}
+    """)
+
+    {:ok, self()}
+  end
+end
diff --git a/lib/dialyxir/dialyzer.ex b/lib/dialyxir/dialyzer.ex
index 42d6690..1e14f9e 100644
--- a/lib/dialyxir/dialyzer.ex
+++ b/lib/dialyxir/dialyzer.ex
@@ -8,6 +8,7 @@ defmodule Dialyxir.Dialyzer do
     def run(args, filterer) do
       try do
         {split, args} = Keyword.split(args, [:raw, :format, :explain])
+
         formatter =
           cond do
             split[:format] == "dialyzer" ->
@@ -30,7 +31,8 @@ defmodule Dialyxir.Dialyzer do
 
             true ->
               :dialyxir
-        end
+          end
+
         {duration_ms, result} = :timer.tc(&:dialyzer.run/1, [args])
 
         formatted_time_elapsed = Formatter.formatted_time(duration_ms)
diff --git a/lib/dialyxir/formatter.ex b/lib/dialyxir/formatter.ex
index 2515c7b..61cacbf 100644
--- a/lib/dialyxir/formatter.ex
+++ b/lib/dialyxir/formatter.ex
@@ -5,6 +5,7 @@ defmodule Dialyxir.Formatter do
   Wrapper around normal Dialyzer warning messages that provides
   example output for error messages.
   """
+  import Dialyxir.Output, only: [info: 1]
 
   @warnings Enum.into(
               [
@@ -195,7 +196,7 @@ defmodule Dialyxir.Formatter do
     warnings_count = Enum.count(warnings)
     filtered_warnings_count = Enum.count(filtered_warnings)
     skipped_count = warnings_count - filtered_warnings_count
-    IO.puts("Total errors: #{warnings_count}, Skipped: #{skipped_count}")
+    info("Total errors: #{warnings_count}, Skipped: #{skipped_count}")
 
     :ok
   end
diff --git a/lib/dialyxir/output.ex b/lib/dialyxir/output.ex
index cde4cc7..8c39a9a 100644
--- a/lib/dialyxir/output.ex
+++ b/lib/dialyxir/output.ex
@@ -2,14 +2,17 @@ defmodule Dialyxir.Output do
   alias IO.ANSI
 
   def color(text, color) when is_binary(text) do
-    if ANSI.enabled? do
+    if ANSI.enabled?() do
       case color do
         :red ->
           ANSI.red() <> text <> ANSI.reset()
+
         :yellow ->
           ANSI.yellow() <> text <> ANSI.reset()
+
         :green ->
           ANSI.green() <> text <> ANSI.reset()
+
         _ ->
           text
       end
@@ -17,4 +20,8 @@ defmodule Dialyxir.Output do
       text
     end
   end
+
+  def info(text), do: Mix.shell().info(text)
+
+  def error(text), do: Mix.shell().error(text)
 end
diff --git a/lib/dialyxir/plt.ex b/lib/dialyxir/plt.ex
index 8fcc5ea..7bbdff4 100644
--- a/lib/dialyxir/plt.ex
+++ b/lib/dialyxir/plt.ex
@@ -5,30 +5,31 @@
 defmodule Dialyxir.Plt do
   @moduledoc false
 
-  import Dialyxir.Output, only: [color: 2]
+  import Dialyxir.Output
 
-  def check(plts, fun \\ &(check_plt/4)) do
+  def check(plts, fun \\ &check_plt/4) do
     find_plts(plts, [], fun)
   end
 
-
   defp find_plts([{plt, apps} | plts], acc, fun) do
     case plt_files(plt) do
       nil ->
         find_plts(plts, [{plt, apps, nil} | acc], fun)
+
       beams ->
-        apps_rest = Enum.flat_map(plts, fn({_plt2, apps2}) -> apps2 end)
+        apps_rest = Enum.flat_map(plts, fn {_plt2, apps2} -> apps2 end)
         apps = Enum.uniq(apps ++ apps_rest)
         check_plts([{plt, apps, beams} | acc], fun)
     end
   end
+
   defp find_plts([], acc, fun) do
     check_plts(acc, fun)
   end
 
   defp check_plts(plts, fun) do
-    _ =Enum.reduce(plts, {nil, MapSet.new(), %{}},
-      fn({plt, apps, beams}, acc) ->
+    _ =
+      Enum.reduce(plts, {nil, MapSet.new(), %{}}, fn {plt, apps, beams}, acc ->
         fun.(plt, apps, beams, acc)
       end)
   end
@@ -44,13 +45,12 @@ defmodule Dialyxir.Plt do
   end
 
   defp cache_mod_diff(new, old) do
-    Enum.flat_map(new,
-      fn({app, {mods, _deps}}) ->
-        case Map.has_key?(old, app) do
-          true -> []
-          false -> mods
-        end
-      end)
+    Enum.flat_map(new, fn {app, {mods, _deps}} ->
+      case Map.has_key?(old, app) do
+        true -> []
+        false -> mods
+      end
+    end)
   end
 
   defp resolve_apps(apps, cache) do
@@ -63,10 +63,12 @@ defmodule Dialyxir.Plt do
 
   defp app_info(app) do
     app_file = Atom.to_charlist(app) ++ '.app'
+
     case :code.where_is_file(app_file) do
       :non_existing ->
         error("Unknown application #{inspect(app)}")
         {app, {[], []}}
+
       app_file ->
         Path.expand(app_file)
         |> read_app_info(app)
@@ -77,8 +79,9 @@ defmodule Dialyxir.Plt do
     case :file.consult(app_file) do
       {:ok, [{:application, ^app, info}]} ->
         parse_app_info(info, app)
+
       {:error, reason} ->
-        Mix.raise "Could not read #{app_file}: #{:file.format_error(reason)}"
+        Mix.raise("Could not read #{app_file}: #{:file.format_error(reason)}")
     end
   end
 
@@ -97,8 +100,8 @@ defmodule Dialyxir.Plt do
 
   defp parse_runtime_dep(runtime_dep) do
     runtime_dep = IO.chardata_to_string(runtime_dep)
-    regex =  ~r/^(.+)\-\d+(?|\.\d+)*$/
-    [app] = Regex.run(regex, runtime_dep, [capture: :all_but_first])
+    regex = ~r/^(.+)\-\d+(?|\.\d+)*$/
+    [app] = Regex.run(regex, runtime_dep, capture: :all_but_first)
     String.to_atom(app)
   end
 
@@ -108,10 +111,12 @@ defmodule Dialyxir.Plt do
 
   defp resolve_module(module, beams) do
     beam = Atom.to_charlist(module) ++ '.beam'
+
     case :code.where_is_file(beam) do
       path when is_list(path) ->
         path = Path.expand(path)
         MapSet.put(beams, path)
+
       :non_existing ->
         error("Unknown module #{inspect(module)}")
         beams
@@ -120,9 +125,11 @@ defmodule Dialyxir.Plt do
 
   defp check_beams(plt, beams, nil, prev_plt) do
     plt_ensure(plt, prev_plt)
+
     case plt_files(plt) do
       nil ->
         Mix.raise("Could not open #{plt}: #{:file.format_error(:enoent)}")
+
       old_beams ->
         check_beams(plt, beams, old_beams)
     end
@@ -147,8 +154,7 @@ defmodule Dialyxir.Plt do
   defp plt_new(plt) do
     info("Creating #{Path.basename(plt)}")
     plt = erl_path(plt)
-    _ = plt_run([analysis_type: :plt_build, output_plt: plt,
-      apps: [:erts]])
+    _ = plt_run(analysis_type: :plt_build, output_plt: plt, apps: [:erts])
     :ok
   end
 
@@ -161,12 +167,12 @@ defmodule Dialyxir.Plt do
     case MapSet.size(files) do
       0 ->
         :ok
+
       n ->
-        (Mix.shell()).info("Adding #{n} modules to #{Path.basename(plt)}")
+        Mix.shell().info("Adding #{n} modules to #{Path.basename(plt)}")
         plt = erl_path(plt)
         files = erl_files(files)
-        _ = plt_run([analysis_type: :plt_add, init_plt: plt,
-          files: files])
+        _ = plt_run(analysis_type: :plt_add, init_plt: plt, files: files)
         :ok
     end
   end
@@ -175,12 +181,12 @@ defmodule Dialyxir.Plt do
     case MapSet.size(files) do
       0 ->
         :ok
+
       n ->
         info("Removing #{n} modules from #{Path.basename(plt)}")
         plt = erl_path(plt)
         files = erl_files(files)
-        _ = plt_run([analysis_type: :plt_remove, init_plt: plt,
-          files: files])
+        _ = plt_run(analysis_type: :plt_remove, init_plt: plt, files: files)
         :ok
     end
   end
@@ -189,10 +195,11 @@ defmodule Dialyxir.Plt do
     case MapSet.size(files) do
       0 ->
         :ok
+
       n ->
-        (Mix.shell()).info("Checking #{n} modules in #{Path.basename(plt)}")
+        Mix.shell().info("Checking #{n} modules in #{Path.basename(plt)}")
         plt = erl_path(plt)
-        _ = plt_run([analysis_type: :plt_check, init_plt: plt])
+        _ = plt_run(analysis_type: :plt_check, init_plt: plt)
         :ok
     end
   end
@@ -202,7 +209,7 @@ defmodule Dialyxir.Plt do
       :dialyzer.run([check_plt: false] ++ opts)
     catch
       {:dialyzer_error, msg} ->
-        IO.puts color(":dialyzer.run error: #{msg}", :red)
+        error(color(":dialyzer.run error: #{msg}", :red))
     end
   end
 
@@ -212,7 +219,7 @@ defmodule Dialyxir.Plt do
   end
 
   defp erl_files(files) do
-    Enum.reduce(files, [], &[erl_path(&1)|&2])
+    Enum.reduce(files, [], &[erl_path(&1) | &2])
   end
 
   defp erl_path(path) do
@@ -222,19 +229,17 @@ defmodule Dialyxir.Plt do
 
   defp plt_files(plt) do
     info("Looking up modules in #{Path.basename(plt)}")
+
     case plt_info(plt) do
       {:ok, info} ->
         Keyword.fetch!(info, :files)
         |> Enum.reduce(MapSet.new(), &MapSet.put(&2, Path.expand(&1)))
+
       {:error, :no_such_file} ->
         nil
+
       {:error, reason} ->
         Mix.raise("Could not open #{plt}: #{:file.format_error(reason)}")
     end
   end
-
-  defp info(msg), do: apply(Mix.shell(), :info, [msg])
-
-  defp error(msg), do: apply(Mix.shell(), :error, [msg])
-
 end
diff --git a/lib/dialyxir/project.ex b/lib/dialyxir/project.ex
index 4c9dfc4..d75b7f6 100644
--- a/lib/dialyxir/project.ex
+++ b/lib/dialyxir/project.ex
@@ -1,5 +1,6 @@
 defmodule Dialyxir.Project do
   @moduledoc false
+  import Dialyxir.Output, only: [info: 1, error: 1]
 
   def plts_list(deps, include_project \\ true, exclude_core \\ false) do
     elixir_apps = [:elixir]
@@ -28,7 +29,7 @@ defmodule Dialyxir.Project do
 
   def check_config do
     if is_binary(dialyzer_config()[:plt_file]) do
-      IO.puts("""
+      info("""
       Notice: :plt_file is deprecated as Dialyxir now uses project-private PLT files by default.
       If you want to use this setting without seeing this warning, provide it in a pair
       with the :no_warn key e.g. `dialyzer: plt_file: {:no_warn, "~/mypltfile"}`
@@ -254,7 +255,7 @@ defmodule Dialyxir.Project do
 
       {:error, err} ->
         nil
-        IO.puts("Error loading #{app}, dependency list may be incomplete.\n #{err}")
+        error("Error loading #{app}, dependency list may be incomplete.\n #{err}")
     end
 
     case Application.spec(app, :applications) do
diff --git a/lib/mix/tasks/dialyzer.ex b/lib/mix/tasks/dialyzer.ex
index 14509b1..4c745f7 100644
--- a/lib/mix/tasks/dialyzer.ex
+++ b/lib/mix/tasks/dialyzer.ex
@@ -13,12 +13,12 @@ defmodule Mix.Tasks.Dialyzer do
     * `--halt-exit-status` - exit immediately with same exit status as dialyzer.
       useful for CI. do not use with `mix do`.
     * `--plt`              - only build the required plt(s) and exit.
-    * `--raw`              - Dump the raw erlang terms returned by dialyzer module (deprecated, use `--format rsw`).
     *  --format short      - format the warnings in a compact format.
     *  --format raw        - format the warnings in format returned before Dialyzer formatting
     *  --format dialyxir   - format the warnings in a pretty printed format
     *  --format dialyzer   - format the warnings in the original Dialyzer format
     *  --explain warning   - explain the class of warnings, e.g. no_return
+    *  --quiet             - suppress all informational messages
 
   Warning flags passed to this task are passed on to `:dialyzer`.
 
@@ -85,6 +85,7 @@ defmodule Mix.Tasks.Dialyzer do
 
   use Mix.Task
   import System, only: [user_home!: 0]
+  import Dialyxir.Output, only: [info: 1, error: 1]
   alias Dialyxir.Project
   alias Dialyxir.Plt
   alias Dialyxir.Dialyzer
@@ -101,6 +102,7 @@ defmodule Mix.Tasks.Dialyzer do
     * `--no-compile`       - do not compile even if needed.
     """
     use Mix.Task
+
     def run(args) do
       Mix.Tasks.Dialyzer.run(["--plt" | args])
     end
@@ -118,79 +120,94 @@ defmodule Mix.Tasks.Dialyzer do
     """
     use Mix.Task
 
-    @command_options [ all: :boolean, ]
+    @command_options [all: :boolean]
     def run(args) do
       {opts, _, _dargs} = OptionParser.parse(args, strict: @command_options)
       Mix.Tasks.Dialyzer.clean(opts)
     end
   end
 
-  @default_warnings [ :unknown ]
-  @command_options [ no_compile: :boolean,
-                     no_check: :boolean,
-                     halt_exit_status: :boolean,
-                     plt: :boolean,
-                     raw: :boolean,
-                     format: :string,
-                     explain: :string
-                   ]
+  @default_warnings [:unknown]
+  @command_options [
+    no_compile: :boolean,
+    no_check: :boolean,
+    halt_exit_status: :boolean,
+    plt: :boolean,
+    quiet: :boolean,
+    raw: :boolean,
+    format: :string,
+    explain: :string
+  ]
 
   def run(args) do
+    {opts, _, dargs} = OptionParser.parse(args, strict: @command_options)
+    original_shell = Mix.shell()
+    if opts[:quiet], do: Mix.shell(Mix.Shell.Quiet)
+    opts = Keyword.delete(opts, :quiet)
     check_dialyzer()
     compatibility_notice()
+
     if Mix.Project.get() do
       Project.check_config()
 
-      {opts, _, dargs} = OptionParser.parse(args, strict: @command_options)
-
       unless opts[:no_compile], do: Mix.Project.compile([])
-      _ = unless no_check?(opts) do
-        IO.puts "Finding suitable PLTs"
-        check_plt()
-      end
+
+      _ =
+        unless no_check?(opts) do
+          info("Finding suitable PLTs")
+          check_plt()
+        end
+
       unless opts[:plt], do: run_dialyzer(opts, dargs)
     else
-      IO.puts "No mix project found - checking core PLTs..."
+      info("No mix project found - checking core PLTs...")
       Project.plts_list([], false) |> Plt.check()
     end
+
+    Mix.shell(original_shell)
   end
 
   def clean(opts, fun \\ &delete_plt/4) do
     check_dialyzer()
     compatibility_notice()
     if opts[:all], do: Project.plts_list([], false) |> Plt.check(fun)
+
     if Mix.Project.get() do
       {apps, _hash} = dependency_hash()
-      IO.puts "Deleting PLTs"
+      info("Deleting PLTs")
       Project.plts_list(apps, true, true) |> Plt.check(fun)
-      IO.puts "About to delete PLT hash file: #{plt_hash_file()}"
+      info("About to delete PLT hash file: #{plt_hash_file()}")
       File.rm(plt_hash_file())
     end
   end
 
   def delete_plt(plt, _, _, _) do
-    IO.puts("About to delete PLT file: #{plt}")
+    info("About to delete PLT file: #{plt}")
     File.rm(plt)
   end
 
   defp no_check?(opts) do
     case {in_child?(), no_plt?()} do
       {true, true} ->
-        IO.puts "In an Umbrella child and no PLT found - building that first."
+        info("In an Umbrella child and no PLT found - building that first.")
         build_parent_plt()
         true
+
       {true, false} ->
-        IO.puts "In an Umbrella child, not checking PLT..."
+        info("In an Umbrella child, not checking PLT...")
         true
-      _ -> opts[:no_check]
+
+      _ ->
+        opts[:no_check]
     end
   end
 
   defp check_plt() do
-    IO.puts "Checking PLT..."
+    info("Checking PLT...")
     {apps, hash} = dependency_hash()
+
     if check_hash?(hash) do
-      IO.puts "PLT is up to date!"
+      info("PLT is up to date!")
     else
       Project.plts_list(apps) |> Plt.check()
       File.write(plt_hash_file(), hash)
@@ -198,29 +215,37 @@ defmodule Mix.Tasks.Dialyzer do
   end
 
   defp run_dialyzer(opts, dargs) do
-    args = [ { :check_plt, false },
-             { :init_plt, String.to_charlist(Project.plt_file()) },
-             { :files_rec, Project.dialyzer_paths() },
-             { :warnings, dialyzer_warnings(dargs) } ,
-             { :explain, opts[:explain]},
-             { :format, opts[:format]},
-             { :raw, opts[:raw] },
-           ]
-
-    IO.puts "Starting Dialyzer"
-    IO.inspect args, label: "dialyzer args"
-    { _, exit_status, result } = Dialyzer.dialyze(args)
-    Enum.each(result, &IO.puts/1)
+    args = [
+      {:check_plt, false},
+      {:init_plt, String.to_charlist(Project.plt_file())},
+      {:files_rec, Project.dialyzer_paths()},
+      {:warnings, dialyzer_warnings(dargs)},
+      {:explain, opts[:explain]},
+      {:format, opts[:format]},
+      {:raw, opts[:raw]}
+    ]
+
+    info("Starting Dialyzer")
+
+    args
+    |> inspect(label: "dialyzer args", pretty: true)
+    |> info
+
+    {status, exit_status, [time | result]} = Dialyzer.dialyze(args)
+    info(time)
+    report = if status == :ok, do: &info/1, else: &error/1
+    Enum.each(result, report)
     if opts[:halt_exit_status], do: :erlang.halt(exit_status)
   end
 
   defp dialyzer_warnings(dargs) do
-    raw_opts = Project.dialyzer_flags() ++ Enum.map(dargs, &elem(&1,0))
-    transform(raw_opts) ++ @default_warnings -- Project.dialyzer_removed_defaults()
+    raw_opts = Project.dialyzer_flags() ++ Enum.map(dargs, &elem(&1, 0))
+    transform(raw_opts) ++ (@default_warnings -- Project.dialyzer_removed_defaults())
   end
 
   defp transform(options) when is_list(options), do: Enum.map(options, &transform/1)
   defp transform(option) when is_atom(option), do: option
+
   defp transform(option) when is_binary(option) do
     option
     |> String.replace_leading("-W", "")
@@ -228,9 +253,8 @@ defmodule Mix.Tasks.Dialyzer do
     |> String.to_atom()
   end
 
-
   defp in_child? do
-    String.contains?(Mix.Project.config[:lockfile], "..")
+    String.contains?(Mix.Project.config()[:lockfile], "..")
   end
 
   defp no_plt? do
@@ -238,49 +262,49 @@ defmodule Mix.Tasks.Dialyzer do
   end
 
   defp build_parent_plt() do
-    parent = Mix.Project.config[:lockfile] |> Path.expand |> Path.dirname
-    opts = [ into: IO.stream(:stdio, :line),
-             stderr_to_stdout: true,
-             cd: parent ]
+    parent = Mix.Project.config()[:lockfile] |> Path.expand() |> Path.dirname()
+    opts = [into: IO.stream(:stdio, :line), stderr_to_stdout: true, cd: parent]
     # It would seem more natural to use Mix.in_project here to start in our parent project.
     # However part of the app.tree resolution includes loading all sub apps, and we will
     # hit an exception when we try to do that for *this* child, which is already loaded.
     {out, rc} = System.cmd("mix", ["dialyzer", "--plt"], opts)
+
     unless rc == 0 do
-      IO.puts("Error building parent PLT, process returned code: #{rc}\n#{out}")
+      info("Error building parent PLT, process returned code: #{rc}\n#{out}")
     end
   end
 
   defp check_dialyzer do
     if not Code.ensure_loaded?(:dialyzer) do
-       IO.puts """
-       DEPENDENCY MISSING
-       ------------------------
-       If you are reading this message, then Elixir and Erlang are installed but the
-       Erlang Dialyzer is not available. Probably this is because you installed Erlang
-       with your OS package manager and the Dialyzer package is separate.
+      error("""
+      DEPENDENCY MISSING
+      ------------------------
+      If you are reading this message, then Elixir and Erlang are installed but the
+      Erlang Dialyzer is not available. Probably this is because you installed Erlang
+      with your OS package manager and the Dialyzer package is separate.
 
-       On Debian/Ubuntu:
+      On Debian/Ubuntu:
 
-         `apt-get install erlang-dialyzer`
+        `apt-get install erlang-dialyzer`
 
-       Fedora:
+      Fedora:
 
-          `yum install erlang-dialyzer`
+         `yum install erlang-dialyzer`
 
-       Arch and Homebrew include Dialyzer in their base erlang packages. Please report a Github
-       issue to add or correct distribution-specific information.
-       """
-       :erlang.halt(3)
-    end
+      Arch and Homebrew include Dialyzer in their base erlang packages. Please report a Github
+      issue to add or correct distribution-specific information.
+      """)
 
+      :erlang.halt(3)
+    end
   end
 
   defp compatibility_notice do
     old_plt = "#{user_home!()}/.dialyxir_core_*.plt"
-    if File.exists?(old_plt) && (!File.exists?(Project.erlang_plt()) || !File.exists?(Project.elixir_plt())) do
 
-      IO.puts """
+    if File.exists?(old_plt) &&
+         (!File.exists?(Project.erlang_plt()) || !File.exists?(Project.elixir_plt())) do
+      info("""
       COMPATIBILITY NOTICE
       ------------------------
       Previous usage of a pre-0.4 version of Dialyxir detected. Please be aware that the 0.4 release
@@ -291,13 +315,13 @@ defmodule Mix.Tasks.Dialyzer do
       (see `mix help dialyzer`).
 
       If you no longer use the older Dialyxir in any projects and do not want to see this notice each time you upgrade your Erlang/Elixir distribution, you can delete your old pre-0.4 PLT files. ( rm ~/.dialyxir_core_*.plt )
-      """
+      """)
     end
   end
 
   @spec check_hash?(binary()) :: boolean()
   defp check_hash?(hash) do
-	  case File.read(plt_hash_file()) do
+    case File.read(plt_hash_file()) do
       {:ok, stored_hash} -> hash == stored_hash
       _ -> false
     end
@@ -307,10 +331,10 @@ defmodule Mix.Tasks.Dialyzer do
 
   @spec dependency_hash :: {[atom()], binary()}
   def dependency_hash do
-    lock_file = Mix.Dep.Lock.read |> :erlang.term_to_binary
-    apps = Project.cons_apps |> IO.inspect
+    lock_file = Mix.Dep.Lock.read() |> :erlang.term_to_binary()
+    apps = Project.cons_apps()
+    apps |> inspect() |> info()
     hash = :crypto.hash(:sha, lock_file <> :erlang.term_to_binary(apps))
     {apps, hash}
   end
-
 end
diff --git a/mix.exs b/mix.exs
index 39cf313..1c474e2 100644
--- a/mix.exs
+++ b/mix.exs
@@ -8,7 +8,7 @@ defmodule Dialyxir.Mixfile do
       elixir: ">= 1.6.0",
       description: description(),
       package: package(),
-      deps: [ {:ex_doc, ">= 0.0.0", only: :dev} ],
+      deps: [{:ex_doc, ">= 0.0.0", only: :dev}],
       dialyzer: [
         plt_apps: [:dialyzer, :elixir, :kernel, :mix, :stdlib],
         ignore_warnings: ".dialyzer_ignore.exs",
@@ -19,13 +19,13 @@ defmodule Dialyxir.Mixfile do
       name: "Dialyxir",
       source_url: "https://github.com/jeremyjh/dialyxir",
       homepage_url: "https://github.com/jeremyjh/dialyxir",
-      docs: [main: "readme", # The main page in the docs
-             extras: ["README.md"]]
+      # The main page in the docs
+      docs: [main: "readme", extras: ["README.md"]]
     ]
   end
 
   def application do
-    [applications: [:dialyzer, :crypto, :mix]]
+    [mod: {Dialyxir, []}, applications: [:dialyzer, :crypto, :mix]]
   end
 
   defp description do
@@ -35,9 +35,11 @@ defmodule Dialyxir.Mixfile do
   end
 
   defp package do
-    [files: ["lib", "mix.exs", "README.md", "LICENSE"],
-     maintainers: ["Jeremy Huffman"],
-     licenses: ["Apache 2.0"],
-     links: %{"GitHub" => "https://github.com/jeremyjh/dialyxir"}]
+    [
+      files: ["lib", "mix.exs", "README.md", "LICENSE"],
+      maintainers: ["Jeremy Huffman"],
+      licenses: ["Apache 2.0"],
+      links: %{"GitHub" => "https://github.com/jeremyjh/dialyxir"}
+    ]
   end
 end


Test patch:
diff --git a/test/dialyxir/dialyzer_test.exs b/test/dialyxir/dialyzer_test.exs
index 8703c4a..99b2b95 100644
--- a/test/dialyxir/dialyzer_test.exs
+++ b/test/dialyxir/dialyzer_test.exs
@@ -7,45 +7,41 @@ defmodule Dialyxir.DialyzerTest do
 
     test "formatting with no warnings" do
       defmodule StubSuccess do
-        def run(_, _), do: { :ok, { "time", [] } }
+        def run(_, _), do: {:ok, {"time", []}}
       end
 
-      { expected_result_code,
-        expected_exit_code,
-        expected_messages } = dialyze(nil, StubSuccess, nil)
+      {expected_result_code, expected_exit_code, expected_messages} =
+        dialyze(nil, StubSuccess, nil)
 
       assert expected_result_code == :ok
       assert expected_exit_code == 0
-      assert expected_messages == ["time",
-                                   "\e[32mdone (passed successfully)\e[0m"]
-
+      assert expected_messages == ["time", "\e[32mdone (passed successfully)\e[0m"]
     end
 
     test "formatting with warnings" do
       defmodule StubWarn do
-        def run(_, _), do: { :ok, { "time", ["warning 1", "warning 2"] } }
+        def run(_, _), do: {:ok, {"time", ["warning 1", "warning 2"]}}
       end
 
-      { expected_result_code,
-        expected_exit_code,
-        expected_messages } = dialyze(nil, StubWarn, nil)
+      {expected_result_code, expected_exit_code, expected_messages} = dialyze(nil, StubWarn, nil)
 
       assert expected_result_code == :warn
       assert expected_exit_code == 2
-      assert expected_messages == ["time",
-                                   "\e[31mwarning 1\e[0m",
-                                   "\e[31mwarning 2\e[0m",
-                                   "\e[33mdone (warnings were emitted)\e[0m"]
+
+      assert expected_messages == [
+               "time",
+               "\e[31mwarning 1\e[0m",
+               "\e[31mwarning 2\e[0m",
+               "\e[33mdone (warnings were emitted)\e[0m"
+             ]
     end
 
     test "formatting with errors" do
       defmodule StubError do
-        def run(_, _), do: { :error, "dialyzer failed" }
+        def run(_, _), do: {:error, "dialyzer failed"}
       end
 
-      { expected_result_code,
-        expected_exit_code,
-        expected_messages } = dialyze(nil, StubError, nil)
+      {expected_result_code, expected_exit_code, expected_messages} = dialyze(nil, StubError, nil)
 
       assert expected_result_code == :error
       assert expected_exit_code == 1
diff --git a/test/dialyxir/project_test.exs b/test/dialyxir/project_test.exs
index 5064bee..8aa9236 100644
--- a/test/dialyxir/project_test.exs
+++ b/test/dialyxir/project_test.exs
@@ -7,6 +7,7 @@ defmodule Dialyxir.ProjectTest do
   defp in_project(app, f) when is_atom(app) do
     Mix.Project.in_project(app, "test/fixtures/#{Atom.to_string(app)}", fn _ -> f.() end)
   end
+
   defp in_project(apps, f) when is_list(apps) do
     path = Enum.map_join(apps, "/", &Atom.to_string/1)
     app = List.last(apps)
@@ -14,118 +15,136 @@ defmodule Dialyxir.ProjectTest do
   end
 
   test "Default Project PLT File in _build dir" do
-    in_project :default_apps, fn ->
+    in_project(:default_apps, fn ->
       assert Regex.match?(~r/_build.*plt/, Project.plt_file())
-    end
+    end)
   end
 
   test "Can specify a different PLT file name" do
-    in_project :local_plt, fn ->
+    in_project(:local_plt, fn ->
       assert Regex.match?(~r/local\.plt/, Project.plt_file())
-    end
+    end)
   end
 
   test "Deprecation warning on use of bare :plt_file" do
-    in_project :local_plt, fn ->
+    in_project(:local_plt, fn ->
       out = capture_io(&Project.check_config/0)
       assert Regex.match?(~r/.*plt_file.*deprecated.*/, out)
-    end
+    end)
   end
 
   test "Can specify a different PLT file name along with :no_warn" do
-    in_project :local_plt_no_warn, fn ->
+    in_project(:local_plt_no_warn, fn ->
       assert Regex.match?(~r/local\.plt/, Project.plt_file())
-    end
+    end)
   end
 
   test "No deprecation warning on use of plt_file: {:no_warn, myfile}" do
-    in_project :local_plt_no_warn, fn ->
+    in_project(:local_plt_no_warn, fn ->
       out = capture_io(&Project.check_config/0)
       refute Regex.match?(~r/.*plt_path.*deprecated.*/, out)
-    end
+    end)
   end
 
   test "App list for default contains direct and
         indirect :application dependencies" do
-    in_project :default_apps, fn ->
-      apps = Project.cons_apps
-      assert Enum.member?(apps, :logger) #direct
-      assert Enum.member?(apps, :public_key) #direct
-      assert Enum.member?(apps, :asn1) #indirect
-    end
+    in_project(:default_apps, fn ->
+      apps = Project.cons_apps()
+      # direct
+      assert Enum.member?(apps, :logger)
+      # direct
+      assert Enum.member?(apps, :public_key)
+      # indirect
+      assert Enum.member?(apps, :asn1)
+    end)
   end
 
   test "App list for umbrella contains child dependencies
   indirect :application dependencies" do
-    in_project :umbrella, fn ->
-      apps = Project.cons_apps
-      assert Enum.member?(apps, :logger) #direct
-      assert Enum.member?(apps, :public_key) #direct, child1
-      assert Enum.member?(apps, :asn1) #indirect
-      assert Enum.member?(apps, :mix) #direct, child2
-    end
+    in_project(:umbrella, fn ->
+      apps = Project.cons_apps()
+      # direct
+      assert Enum.member?(apps, :logger)
+      # direct, child1
+      assert Enum.member?(apps, :public_key)
+      # indirect
+      assert Enum.member?(apps, :asn1)
+      # direct, child2
+      assert Enum.member?(apps, :mix)
+    end)
   end
 
   @tag :skip
   test "App list for umbrella contains all child dependencies
   when run from child directory" do
-    in_project [:umbrella, :apps, :second_one], fn ->
-      apps = Project.cons_apps
-      assert Enum.member?(apps, :logger) #direct
-      assert Enum.member?(apps, :public_key) #direct, child1
-      assert Enum.member?(apps, :asn1) #indirect
-      assert Enum.member?(apps, :mix) #direct, child2
-    end
+    in_project([:umbrella, :apps, :second_one], fn ->
+      apps = Project.cons_apps()
+      # direct
+      assert Enum.member?(apps, :logger)
+      # direct, child1
+      assert Enum.member?(apps, :public_key)
+      # indirect
+      assert Enum.member?(apps, :asn1)
+      # direct, child2
+      assert Enum.member?(apps, :mix)
+    end)
   end
 
   test "App list for :apps_direct contains only direct dependencies" do
-    in_project :direct_apps, fn ->
-      apps = Project.cons_apps
-      assert Enum.member?(apps, :logger) #direct
-      assert Enum.member?(apps, :public_key) #direct
-      refute Enum.member?(apps, :asn1) #indirect
-    end
+    in_project(:direct_apps, fn ->
+      apps = Project.cons_apps()
+      # direct
+      assert Enum.member?(apps, :logger)
+      # direct
+      assert Enum.member?(apps, :public_key)
+      # indirect
+      refute Enum.member?(apps, :asn1)
+    end)
   end
 
   test "Core PLT files located in mix home by default" do
-    in_project :default_apps, fn ->
+    in_project(:default_apps, fn ->
       assert String.contains?(Project.erlang_plt(), Mix.Utils.mix_home())
-    end
+    end)
   end
 
   test "Core PLT file paths can be specified with :plt_core_path" do
-    in_project :alt_core_path, fn ->
+    in_project(:alt_core_path, fn ->
       assert String.contains?(Project.erlang_plt(), "_build")
-    end
+    end)
   end
 
   test "By default core elixir and erlang plts are in mix.home" do
-    in_project :default_apps, fn ->
+    in_project(:default_apps, fn ->
       assert String.contains?(Project.erlang_plt(), Mix.Utils.mix_home())
-    end
+    end)
   end
 
   test "By default a dialyzer ignore file is nil" do
-    in_project :default_apps, fn ->
-      assert Project.dialyzer_ignore_warnings == nil
-    end
+    in_project(:default_apps, fn ->
+      assert Project.dialyzer_ignore_warnings() == nil
+    end)
   end
 
   test "Filtered dialyzer warnings" do
-    in_project :default_apps, fn ->
-      output_list = ~S"""
-      project.ex:9 This should still be here
-      project.ex:9: Guard test is_atom(_@5::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
-      project.ex:9: Guard test is_binary(_@4::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
-      """ |> String.trim_trailing("\n") |> String.split("\n")
+    in_project(:default_apps, fn ->
+      output_list =
+        ~S"""
+        project.ex:9 This should still be here
+        project.ex:9: Guard test is_atom(_@5::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
+        project.ex:9: Guard test is_binary(_@4::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
+        """
+        |> String.trim_trailing("\n")
+        |> String.split("\n")
 
       pattern = ~S"""
       Guard test is_atom(_@5::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
 
       Guard test is_binary(_@4::#{'__exception__':='true', '__struct__':=_, _=>_}) can never succeed
       """
+
       lines = Project.filter_warnings(output_list, pattern)
       assert lines == ["project.ex:9 This should still be here"]
-    end
+    end)
   end
 end
diff --git a/test/fixtures/alt_core_path/mix.exs b/test/fixtures/alt_core_path/mix.exs
index e040541..046fce8 100644
--- a/test/fixtures/alt_core_path/mix.exs
+++ b/test/fixtures/alt_core_path/mix.exs
@@ -2,9 +2,6 @@ defmodule AltCorePath.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :alt_core_path,
-     version: "1.0.0",
-     dialyzer: [plt_core_path: "_build"]]
+    [app: :alt_core_path, version: "1.0.0", dialyzer: [plt_core_path: "_build"]]
   end
-
 end
diff --git a/test/fixtures/default_apps/mix.exs b/test/fixtures/default_apps/mix.exs
index 1af972f..a0055c0 100644
--- a/test/fixtures/default_apps/mix.exs
+++ b/test/fixtures/default_apps/mix.exs
@@ -2,9 +2,7 @@ defmodule DefaultApps.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :default_apps,
-     version: "0.1.0",
-     deps: deps()]
+    [app: :default_apps, version: "0.1.0", deps: deps()]
   end
 
   def application do
diff --git a/test/fixtures/direct_apps/mix.exs b/test/fixtures/direct_apps/mix.exs
index e22235d..8d9824d 100644
--- a/test/fixtures/direct_apps/mix.exs
+++ b/test/fixtures/direct_apps/mix.exs
@@ -2,11 +2,7 @@ defmodule DirectApps.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :direct_apps,
-     version: "0.1.0",
-     deps: deps(),
-     dialyzer: [plt_add_deps: :apps_direct]
-    ]
+    [app: :direct_apps, version: "0.1.0", deps: deps(), dialyzer: [plt_add_deps: :apps_direct]]
   end
 
   def application do
diff --git a/test/fixtures/local_plt/mix.exs b/test/fixtures/local_plt/mix.exs
index caac686..a5577dc 100644
--- a/test/fixtures/local_plt/mix.exs
+++ b/test/fixtures/local_plt/mix.exs
@@ -2,9 +2,6 @@ defmodule LocalPlt.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :local_plt,
-     version: "1.0.0",
-     dialyzer: [plt_file: "local.plt"]]
+    [app: :local_plt, version: "1.0.0", dialyzer: [plt_file: "local.plt"]]
   end
-
 end
diff --git a/test/fixtures/local_plt_no_warn/mix.exs b/test/fixtures/local_plt_no_warn/mix.exs
index 855c367..821cea5 100644
--- a/test/fixtures/local_plt_no_warn/mix.exs
+++ b/test/fixtures/local_plt_no_warn/mix.exs
@@ -2,9 +2,6 @@ defmodule LocalPltNoWarn.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :local_plt_no_warn,
-     version: "1.0.0",
-     dialyzer: [plt_file: {:no_warn,"local.plt"}]]
+    [app: :local_plt_no_warn, version: "1.0.0", dialyzer: [plt_file: {:no_warn, "local.plt"}]]
   end
-
 end
diff --git a/test/fixtures/umbrella/apps/first_one/mix.exs b/test/fixtures/umbrella/apps/first_one/mix.exs
index aeb379b..416dee3 100644
--- a/test/fixtures/umbrella/apps/first_one/mix.exs
+++ b/test/fixtures/umbrella/apps/first_one/mix.exs
@@ -2,16 +2,18 @@ defmodule FirstOne.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :first_one,
-     version: "0.1.0",
-     build_path: "../../_build",
-     config_path: "../../config/config.exs",
-     deps_path: "../../deps",
-     lockfile: "../../mix.lock",
-     elixir: "~> 1.3",
-     build_embedded: Mix.env == :prod,
-     start_permanent: Mix.env == :prod,
-     deps: []]
+    [
+      app: :first_one,
+      version: "0.1.0",
+      build_path: "../../_build",
+      config_path: "../../config/config.exs",
+      deps_path: "../../deps",
+      lockfile: "../../mix.lock",
+      elixir: "~> 1.3",
+      build_embedded: Mix.env() == :prod,
+      start_permanent: Mix.env() == :prod,
+      deps: []
+    ]
   end
 
   # Configuration for the OTP application
@@ -20,5 +22,4 @@ defmodule FirstOne.Mixfile do
   def application do
     [applications: [:logger, :public_key]]
   end
-
 end
diff --git a/test/fixtures/umbrella/apps/second_one/mix.exs b/test/fixtures/umbrella/apps/second_one/mix.exs
index 80f2ac7..b3aa30b 100644
--- a/test/fixtures/umbrella/apps/second_one/mix.exs
+++ b/test/fixtures/umbrella/apps/second_one/mix.exs
@@ -2,16 +2,18 @@ defmodule SecondOne.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :second_one,
-     version: "0.1.0",
-     build_path: "../../_build",
-     config_path: "../../config/config.exs",
-     deps_path: "../../deps",
-     lockfile: "../../mix.lock",
-     elixir: "~> 1.3",
-     build_embedded: Mix.env == :prod,
-     start_permanent: Mix.env == :prod,
-     deps: []]
+    [
+      app: :second_one,
+      version: "0.1.0",
+      build_path: "../../_build",
+      config_path: "../../config/config.exs",
+      deps_path: "../../deps",
+      lockfile: "../../mix.lock",
+      elixir: "~> 1.3",
+      build_embedded: Mix.env() == :prod,
+      start_permanent: Mix.env() == :prod,
+      deps: []
+    ]
   end
 
   # Configuration for the OTP application
@@ -20,5 +22,4 @@ defmodule SecondOne.Mixfile do
   def application do
     [applications: [:logger, :mix]]
   end
-
 end
diff --git a/test/fixtures/umbrella/mix.exs b/test/fixtures/umbrella/mix.exs
index 71c6b7f..1937961 100644
--- a/test/fixtures/umbrella/mix.exs
+++ b/test/fixtures/umbrella/mix.exs
@@ -2,10 +2,11 @@ defmodule Umbrella.Mixfile do
   use Mix.Project
 
   def project do
-    [apps_path: "apps",
-     build_embedded: Mix.env == :prod,
-     start_permanent: Mix.env == :prod,
-     deps: []]
+    [
+      apps_path: "apps",
+      build_embedded: Mix.env() == :prod,
+      start_permanent: Mix.env() == :prod,
+      deps: []
+    ]
   end
-
 end
diff --git a/test/mix/tasks/dialyzer_test.exs b/test/mix/tasks/dialyzer_test.exs
index ef7296a..772d653 100644
--- a/test/mix/tasks/dialyzer_test.exs
+++ b/test/mix/tasks/dialyzer_test.exs
@@ -25,9 +25,9 @@ defmodule Mix.Tasks.DialyzerTest do
       fun = fn -> Mix.Tasks.Dialyzer.clean([], &no_delete_plt/4) end
 
       assert not Regex.match?(
-        ~r/About to delete PLT file: .*dialyxir_erlang/,
-        capture_io(fun)
-      )
+               ~r/About to delete PLT file: .*dialyxir_erlang/,
+               capture_io(fun)
+             )
     end)
   end
 
@@ -36,10 +36,17 @@ defmodule Mix.Tasks.DialyzerTest do
       fun = fn -> Mix.Tasks.Dialyzer.clean([{:all, true}], &no_delete_plt/4) end
 
       assert Regex.match?(
-        ~r/About to delete PLT file: .*dialyxir_erlang/,
-        capture_io(fun)
-      )
+               ~r/About to delete PLT file: .*dialyxir_erlang/,
+               capture_io(fun)
+             )
     end)
   end
 
+  @tag :output_tests
+  test "Informational output is suppressed with --quiet" do
+    args = ["dialyzer", "--quiet"]
+    env = [{"MIX_ENV", "prod"}]
+    {result, 0} = System.cmd("mix", args, env: env)
+    assert result == ""
+  end
 end
diff --git a/test/pretty_print_test.exs b/test/pretty_print_test.exs
index 246aa7f..79043e2 100644
--- a/test/pretty_print_test.exs
+++ b/test/pretty_print_test.exs
@@ -1,5 +1,4 @@
 defmodule Dialyxir.Test.PretyPrintTest do
-
   use ExUnit.Case
 
   test "simple atoms are pretty printed appropriately" do
@@ -75,7 +74,9 @@ defmodule Dialyxir.Test.PretyPrintTest do
   end
 
   test "or'd mixed types function signatures are pretty printed appropriately" do
-    input = "('Elixir.Plug.Conn':t(),binary() | atom(),'Elixir.Keyword':t() | map()) -> 'Elixir.Plug.Conn':t()"
+    input =
+      "('Elixir.Plug.Conn':t(),binary() | atom(),'Elixir.Keyword':t() | map()) -> 'Elixir.Plug.Conn':t()"
+
     pretty_printed = Dialyxir.PrettyPrint.pretty_print(input)
 
     expected_output = "(Plug.Conn.t(), binary() | atom(), Keyword.t() | map()) :: Plug.Conn.t()"
@@ -151,10 +152,14 @@ defmodule Dialyxir.Test.PretyPrintTest do
   end
 
   test "erlang function calls are pretty printed appropriately" do
-    input = "([supervisor:child_spec() | {module(),term()} | module()],[init_option()]) -> {'ok',tuple()}"
+    input =
+      "([supervisor:child_spec() | {module(),term()} | module()],[init_option()]) -> {'ok',tuple()}"
+
     pretty_printed = Dialyxir.PrettyPrint.pretty_print(input)
 
-    expected_output = "([:supervisor.child_spec() | {module(), term()} | module()], [init_option()]) :: {:ok, tuple()}"
+    expected_output =
+      "([:supervisor.child_spec() | {module(), term()} | module()], [init_option()]) :: {:ok, tuple()}"
+
     assert pretty_printed == expected_output
   end
 
@@ -186,11 +191,13 @@ defmodule Dialyxir.Test.PretyPrintTest do
         #<100>(8, 1, 'integer', ['unsigned', 'big']),
         #<101>(8, 1, 'integer', ['unsigned', 'big'])}# :='nil'}}
     """
+
     pretty_printed = Dialyxir.PrettyPrint.pretty_print_pattern(input)
 
-    expected_output = String.trim("""
-    conn = %{:params => %{"include" => nil}}
-    """)
+    expected_output =
+      String.trim("""
+      conn = %{:params => %{"include" => nil}}
+      """)
 
     assert pretty_printed == expected_output
   end
@@ -225,12 +232,13 @@ defmodule Dialyxir.Test.PretyPrintTest do
 
     expected_output = "Module.V1.Foo"
     assert pretty_printed == expected_output
-    end
+  end
 
   test "integers in maps are pretty printed appropriately" do
     input = ~S"""
     #{'source':={[any()] | 98971880 | map()}}
     """
+
     pretty_printed = Dialyxir.PrettyPrint.pretty_print(input)
 
     expected_output = "%{:source => {[any()] | 98971880 | map()}}"
@@ -241,6 +249,7 @@ defmodule Dialyxir.Test.PretyPrintTest do
     input = ~S"""
     fun()
     """
+
     pretty_printed = Dialyxir.PrettyPrint.pretty_print(input)
 
     expected_output = "(... -> any)"
@@ -251,6 +260,7 @@ defmodule Dialyxir.Test.PretyPrintTest do
     input = ~S"""
     'Elixir.MapSet':t('Elixir.MapSet':t(_))
     """
+
     pretty_printed = Dialyxir.PrettyPrint.pretty_print(input)
 
     expected_output = "MapSet.t(MapSet.t(_))"
@@ -275,9 +285,14 @@ defmodule Dialyxir.Test.PretyPrintTest do
     pretty_printed =
       input
       |> to_charlist()
-      |> Dialyxir.PrettyPrint.pretty_print_contract("'Elixir.Module.V1.Ac(tion.Hel(pers'", "foo_bar")
+      |> Dialyxir.PrettyPrint.pretty_print_contract(
+        "'Elixir.Module.V1.Ac(tion.Hel(pers'",
+        "foo_bar"
+      )
+
+    expected_output =
+      "Contract head: (any(), nil) :: nilContract head: (Ecto.Queryable.t(), String.t()) :: String.t()"
 
-    expected_output = "Contract head: (any(), nil) :: nilContract head: (Ecto.Queryable.t(), String.t()) :: String.t()"
     assert pretty_printed == expected_output
   end
 end
diff --git a/test/test_helper.exs b/test/test_helper.exs
index 869559e..e9afbb1 100644
--- a/test/test_helper.exs
+++ b/test/test_helper.exs
@@ -1,1 +1,4 @@
-ExUnit.start()
+case System.get_env("OUTPUT_TESTS") do
+  "true" -> ExUnit.start(exclude: :test, include: :output_tests)
+  _ -> ExUnit.start(exclude: :output_tests)
+end
diff --git a/test/warning_test.exs b/test/warning_test.exs
index 4a43417..d958cb7 100644
--- a/test/warning_test.exs
+++ b/test/warning_test.exs
@@ -1,5 +1,4 @@
 defmodule Dialyxir.Test.WarningTest do
-
   use ExUnit.Case
 
   # Don't test output in here, just that it can succeed.