# Testing compile time errors

**URL:** <https://forum.crystal-lang.org/t/testing-compile-time-errors/272>\
**Category:** Help & Support\
**Created:** [January 12, 2019, 4:28pm UTC](https://forum.crystal-lang.org/t/testing-compile-time-errors/272 "2019-01-12T16:28:33Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 12, 2019, 4:28pm UTC](https://forum.crystal-lang.org/t/testing-compile-time-errors/272/1 "2019-01-12T16:28:33Z")

</div>

I have some checks in my projects that will throw compile time errors if you do not have a required method defined, or adding an annotation to an instance method vs class method.

Is there a way to test these compile time error get thrown as expected; similar to `expect_raises` or the `assert_error` method in the stdlib?

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [January 12, 2019, 10:05pm UTC](https://forum.crystal-lang.org/t/testing-compile-time-errors/272/2 "2019-01-12T22:05:22Z")

</div>

This is essentially [https://github.com/crystal-lang/crystal/issues/2391](https://github.com/crystal-lang/crystal/issues/2391)

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 12, 2019, 10:08pm UTC](https://forum.crystal-lang.org/t/testing-compile-time-errors/272/3 "2019-01-12T22:08:09Z")

</div>

Similar, would be more interested in making sure the correct compile time error is thrown than just a true/false if it compiles or not tho.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [April 13, 2019, 12:21am UTC](https://forum.crystal-lang.org/t/testing-compile-time-errors/272/4 "2019-04-13T00:21:36Z")

</div>

Just to complete this topic. This is what i ended up doing:

```auto
def assert_error(path : String, message : String) : Nil
  buffer = IO::Memory.new
  result = Process.run("crystal", ["run", "--no-color", "--no-codegen", "spec/" + path], error: buffer)
  result.success?.should be_false
  buffer.to_s.should contain message
  buffer.close
end

```

Where i created separate files for each assertion, like:

```auto
require "../../../routing_spec_helper"

class CompileController < Athena::Routing::Controller
  @[Athena::Routing::Get(path: "int8/")]
  def no_return_type
    123
  end
end

Athena::Routing.run

```

Then used it

```auto
    describe "without a return type" do
      it "should not compile" do
        assert_error "routing/compiler/actions/no_return_type.cr", "Route action return type must be set for 'CompileController.no_return_type'"
      end
    end

```

EDIT: I created [GitHub - athena-framework/spec: Common/helpful Spec compliant testing utilities](https://github.com/athena-framework/spec) that includes this among other additional testing utilities.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [January 3, 2022, 3:01pm UTC](https://forum.crystal-lang.org/t/testing-compile-time-errors/272/5 "2022-01-03T15:01:41Z")

</div>

Update: Actually came up with a bit better way to handle it:

```auto
private def assert_error(message : String, code : String) : Nil
  input = IO::Memory.new <<-CR
    require "./spec_helper.cr"
    #{code}
    ATH.run
  CR

  buffer = IO::Memory.new
  result = Process.run("crystal", ["run", "--no-color", "--no-codegen", "--stdin-filename", "#{ __DIR__ }/test.cr"], input: input.rewind, output: buffer, error: buffer)
  fail buffer.to_s if result.success?
  buffer.to_s.should contain message
  buffer.close
end

```

This method allows passing the code as a string to the method as opposed to a file path. This ultimately is easier to maintain. Example use would be like:

```auto
it "action missing return type" do
  assert_error "Route action return type must be set for 'CompileController#action'.", <<-CODE
    class CompileController < Athena::Framework::Controller
      @[ARTA::Get(path: "/")]
      def action
        123
      end
    end
  CODE
end

```
