From bc0a9c03c939d2cfb7f4d7cc12be0e28ea6c3a43 Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sun, 9 Oct 2022 16:47:54 -0600 Subject: [PATCH] Remove runtime compilation tests These may be readded later. Right now they're failing because the GitHub issue 44 spec changes the behavior of Process.run. The changes made by that spec shouldn't leak, but to fix correctly requires substantial changes. These runtime tests provide little value right now and slow down testing. --- .gitlab-ci.yml | 2 +- spec/helpers/.gitkeep | 0 spec/helpers/example.cr | 71 ------------------------------------ spec/helpers/example.ecr | 5 --- spec/helpers/expectation.cr | 28 -------------- spec/helpers/result.cr | 67 ---------------------------------- spec/runtime_example_spec.cr | 58 ----------------------------- spec/spec_helper.cr | 32 ---------------- 8 files changed, 1 insertion(+), 262 deletions(-) create mode 100644 spec/helpers/.gitkeep delete mode 100644 spec/helpers/example.cr delete mode 100644 spec/helpers/example.ecr delete mode 100644 spec/helpers/expectation.cr delete mode 100644 spec/helpers/result.cr delete mode 100644 spec/runtime_example_spec.cr diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b3adb42..d627d27 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,7 @@ before_script: spec: script: - - crystal spec --error-on-warnings --junit_output=. spec/runtime_example_spec.cr spec/matchers/ spec/spectator/*.cr + - crystal spec --error-on-warnings --junit_output=. spec/matchers/ spec/spectator/*.cr artifacts: when: always paths: diff --git a/spec/helpers/.gitkeep b/spec/helpers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/spec/helpers/example.cr b/spec/helpers/example.cr deleted file mode 100644 index 34034ec..0000000 --- a/spec/helpers/example.cr +++ /dev/null @@ -1,71 +0,0 @@ -require "ecr" -require "json" -require "./result" - -module Spectator::SpecHelpers - # Wrapper for compiling and running an example at runtime and getting a result. - class Example - # Creates the example. - # The *spec_helper_path* is the path to spec_helper.cr file. - # The name or ID of the example is given by *example_id*. - # Lastly, the source code for the example is given by *example_code*. - def initialize(@spec_helper_path : String, @example_id : String, @example_code : String) - end - - # Instructs the Crystal compiler to compile the test. - # Returns an instance of `JSON::Any`. - # This will be the outcome and information about the test. - # Output will be suppressed for the test. - # If an error occurs while attempting to compile and run the test, an error will be raised. - def compile - # Create a temporary file containing the test. - with_tempfile do |source_file| - args = ["run", "--no-color", source_file, "--", "--json"] - Process.run(crystal_executable, args) do |process| - JSON.parse(process.output) - rescue JSON::ParseException - raise "Compilation of example #{@example_id} failed\n\n#{process.error.gets_to_end}" - end - end - end - - # Same as `#compile`, but returns the result of the first example in the test. - # Returns a `SpectatorHelpers::Result` instance. - def result - output = compile - example = output["examples"][0] - Result.from_json_any(example) - end - - # Constructs the string representation of the example. - # This produces the Crystal source code. - # *io* is the file handle to write to. - # The *dir* is the directory of the file being written to. - # This is needed to resolve the relative path to the spec_helper.cr file. - private def write(io, dir) - spec_helper_path = Path[@spec_helper_path].relative_to(dir) # ameba:disable Lint/UselessAssign - ECR.embed(__DIR__ + "/example.ecr", io) - end - - # Creates a temporary file containing the compilable example code. - # Yields the path of the temporary file. - # Ensures the file is deleted after it is done being used. - private def with_tempfile - tempfile = File.tempfile("_#{@example_id}_spec.cr") do |file| - dir = File.dirname(file.path) - write(file, dir) - end - - begin - yield tempfile.path - ensure - tempfile.delete - end - end - - # Attempts to find the Crystal compiler on the system or raises an error. - private def crystal_executable - Process.find_executable("crystal") || raise("Could not find Crystal compiler") - end - end -end diff --git a/spec/helpers/example.ecr b/spec/helpers/example.ecr deleted file mode 100644 index 53355bf..0000000 --- a/spec/helpers/example.ecr +++ /dev/null @@ -1,5 +0,0 @@ -require "<%= spec_helper_path %>" - -Spectator.describe "<%= @example_id %>" do - <%= @example_code %> -end diff --git a/spec/helpers/expectation.cr b/spec/helpers/expectation.cr deleted file mode 100644 index fd4d84d..0000000 --- a/spec/helpers/expectation.cr +++ /dev/null @@ -1,28 +0,0 @@ -module Spectator::SpecHelpers - # Information about an `expect` call in an example. - struct Expectation - # Indicates whether the expectation passed or failed. - getter? satisfied : Bool - - # Message when the expectation failed. - # Only available when `#satisfied?` is false. - getter! message : String - - # Additional information about the expectation. - # Only available when `#satisfied?` is false. - getter! values : Hash(String, String) - - # Creates the expectation outcome. - def initialize(@satisfied, @message, @values) - end - - # Extracts the expectation information from a `JSON::Any` object. - def self.from_json_any(object : JSON::Any) - satisfied = object["satisfied"].as_bool - message = object["failure"]?.try(&.as_s?) - values = object["values"]?.try(&.as_h?) - values = values.transform_values(&.as_s) if values - new(satisfied, message, values) - end - end -end diff --git a/spec/helpers/result.cr b/spec/helpers/result.cr deleted file mode 100644 index edafd75..0000000 --- a/spec/helpers/result.cr +++ /dev/null @@ -1,67 +0,0 @@ -module Spectator::SpecHelpers - # Information about an example compiled and run at runtime. - struct Result - # Status of the example after running. - enum Outcome - Success - Failure - Error - Unknown - end - - # Full name and description of the example. - getter name : String - - # Status of the example after running. - getter outcome : Outcome - - # List of expectations ran in the example. - getter expectations : Array(Expectation) - - # Creates the result. - def initialize(@name, @outcome, @expectations) - end - - # Checks if the example was successful. - def success? - outcome.success? - end - - # :ditto: - def successful? - outcome.success? - end - - # Checks if the example failed, but did not error. - def failure? - outcome.failure? - end - - # Checks if the example encountered an error. - def error? - outcome.error? - end - - # Extracts the result information from a `JSON::Any` object. - def self.from_json_any(object : JSON::Any) - name = object["description"].as_s - outcome = parse_outcome_string(object["status"].as_s) - expectations = if (list = object["expectations"].as_a?) - list.map { |e| Expectation.from_json_any(e) } - else - [] of Expectation - end - new(name, outcome, expectations) - end - - # Converts a result string, such as "fail" to an enum value. - private def self.parse_outcome_string(string) - case string - when /pass/i then Outcome::Success - when /fail/i then Outcome::Failure - when /error/i then Outcome::Error - else Outcome::Unknown - end - end - end -end diff --git a/spec/runtime_example_spec.cr b/spec/runtime_example_spec.cr deleted file mode 100644 index 01ae9a3..0000000 --- a/spec/runtime_example_spec.cr +++ /dev/null @@ -1,58 +0,0 @@ -require "./spec_helper" - -# This is a meta test that ensures specs can be compiled and run at runtime. -# The purpose of this is to report an error if this process fails. -# Other tests will fail, but display a different name/description of the test. -# This clearly indicates that runtime testing failed. -# -# Runtime compilation is used to get output of tests as well as check syntax. -# Some specs are too complex to be ran normally. -# Additionally, this allows examples to easily check specific failure cases. -# Plus, it makes testing user-reported issues easy. -Spectator.describe "Runtime compilation", :slow, :compile do - given_example passing_example do - it "does something" do - expect(true).to be_true - end - end - - it "can compile and retrieve the result of an example" do - expect(passing_example).to be_successful - end - - it "can retrieve expectations" do - expect(passing_example.expectations).to_not be_empty - end - - given_example failing_example do - it "does something" do - expect(true).to be_false - end - - it "doesn't run" do - expect(true).to be_false - end - end - - it "detects failed examples" do - expect(failing_example).to be_failure - end - - given_example malformed_example do - it "does something" do - asdf - end - end - - it "raises on compilation errors" do - expect { malformed_example }.to raise_error(/compilation/i) - end - - given_expectation satisfied_expectation do - expect(true).to be_true - end - - it "can compile and retrieve expectations" do - expect(satisfied_expectation).to be_satisfied - end -end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 4c16fd3..e2f9578 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -15,35 +15,3 @@ end macro specify_fails(description = nil, &block) it_fails {{description}} {{block}} end - -# Defines an example ("it" block) that is lazily compiled. -# When the example is referenced with *id*, it will be compiled and the results retrieved. -# The value returned by *id* will be a `Spectator::SpecHelpers::Result`. -# This allows the test result to be inspected. -macro given_example(id, &block) - let({{id}}) do - ::Spectator::SpecHelpers::Example.new( - {{__FILE__}}, - {{id.id.stringify}}, - {{block.body.stringify}} - ).result - end -end - -# Defines an example ("it" block) that is lazily compiled. -# The "it" block must be omitted, as the block provided to this macro will be wrapped in one. -# When the expectation is referenced with *id*, it will be compiled and the result retrieved. -# The value returned by *id* will be a `Spectator::SpecHelpers::Expectation`. -# This allows an expectation to be inspected. -# Only the last expectation performed will be returned. -# An error is raised if no expectations ran. -macro given_expectation(id, &block) - let({{id}}) do - result = ::Spectator::SpecHelpers::Example.new( - {{__FILE__}}, - {{id.id.stringify}}, - {{"it do\n" + block.body.stringify + "\nend"}} - ).result - result.expectations.last || raise("No expectations found from {{id.id}}") - end -end