New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Clean Up and Dry Tests #344
Conversation
|
||
CONT | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Crystal will create whitespace based on the closing CONT
, so you can do:
module CLIFixtures
def expected_controller
<<-CONT
class AnimalController < ApplicationController
def add
render("add.slang")
end
def list
render("list.slang")
end
def remove
render("remove.slang")
end
end
CONT
end
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was confused about this, fixing it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The closing CONT
should align with class
and the last end
@eliasjpr Thanks for your work on this. I like a lot of the refactoring so far (particularly My main concern is moving |
I agree when having 1 assertion line, but when there is multiple line attempting to assert related expectations we should have them in a composed assert method, this makes it very reusable, readable and follow the one assert rule. IMHO An example of this is when asserting if the encryption files exists after encrypting. File.exists?("config/environments/#{enc_file}").should be_true
File.read(enc_key).size.should eq 44 |
I think "Assert" in the AAA pattern is roughly equal to I think the idea behind the one assertion per test, is to make each test ( Using this spec file as a starting point describe MainCommand::Encrypt do
context "application structure" do
it "creates amber directory structure" do
scaffold_app(TESTING_APP)
MainCommand.run ["encrypt", "test"]
assert_encrypted_files_exists?(".test.enc", ".amber_secret_key")
cleanup
end
end
end The I would like to see that our goal is to have each describe MainCommand::Encrypt do
begin
scaffold_app(TESTING_APP)
arg = "test"
MainCommand.run ["encrypt", arg]
it "should create an hidden .[arg].enc file" do
File.exists?("config/environments/.#{arg}.enc").should be_true
end
it "should create a 44 character secret key in .amber_secret_key" do
File.read(".amber_secret_key").size.should eq 44
end
ensure
cleanup
end
end I know it isn't always practical to have a 1:1 |
Thats what I am looking for! Thanks @marksiemers |
It isn't bad practice to setup descriptions for all your known requirements right away: module Amber::CLI
describe MainCommand::Perform do
it "performs a tasks via command line" {} # `it` requires a block
it "performs a tasks via command line alias" {}
it "shows task description" {}
end
end |
070aac6
to
55e81b4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eliasjpr - Overall, this is great. The organization into helpers and fixtures looks really good.
I have some inline comments about renaming/restructuring the outlines of some of the specs, but again, this mostly looks great.
|
||
context "when scaffolding an Amber app" do | ||
scaffold_app(TESTING_APP) | ||
MainCommand.run ["generate", "scaffold", "Animal", "name:string"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line shouldn't be needed to test a shards build
- did we just want something in there?
If we want a more complete test, it should be structured something like this:
context "scaffolding an Amber app"
assert that it builds
test scaffold generator (in a describe block)
test controller generator (in a describe block)
test model generator (in a describe block)
...test each generator...
assert that it still builds
cleanup
end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Practically speaking, we may not want two builds, until the shard downloading thing is optimized one way or another.
It might be better to test the shard building at the end - will it build after all the generators have been run, or did any of them introduce a compile time error?
cleanup | ||
end | ||
|
||
context "when generating controllers" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Semantically, I would say we are in the context of "scaffolding and amber app" and this should be describe "amber generate controller"
MainCommand.run ["generate", "controller", controller] | options | ||
|
||
it "generates controller with correct verbs and actions" do | ||
File.read("./src/controllers/#{controller.downcase}_controller.cr").should eq expected_controller |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line and line 25 are coupling this code with wherever expected_controller
is defined. I would say choose one place and have both controller = "Animal"
and whatever is in the definition of expected_controller
. I think the helper or the fixture is the better place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For an example of how I approached it, see here: 3220d13
And the helper here: https://github.com/marksiemers/amber/blob/3220d1312608f53ca486b8f5a668219870c19b57/spec/amber/cli/templates/migration_spec_helper.cr
All the decisions about names are in the helper - so they are easier to keep in sync.
end | ||
|
||
def layout_with_template | ||
%(<html>\n <body>\n <h1>Hello World</h1>\n<p>I am glad you came</p>\n </body>\n</html>) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for this not to use a heredoc like the others?
spec/amber/cli/commands/init_spec.cr
Outdated
Amber::CLI::Spec.cleanup | ||
end | ||
describe MainCommand::New do | ||
context "application structure" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call this describe "amber new #{TESTING_APP}"
spec/amber/cli/commands/init_spec.cr
Outdated
end | ||
|
||
context "template" do | ||
cleanup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be necessary?
HTML | ||
|
||
TestController.new(context).render_with_csrf.should eq html_output | ||
TestController.new(context).render_with_csrf.should eq csrf_form |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this looks so much better with the refactor, nice work.
end | ||
end | ||
|
||
CONT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as you move the closing CONT
over, you can safely indent the string.
include CookieHelper | ||
include RouterHelper | ||
include WebsocketsHelper | ||
include ValidationsHelper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like this organization.
This organizes and cleans up and DRY the CLI specs making it more readable and cohesive.
64e053b
to
fad1d3c
Compare
a85af50
to
0b6caad
Compare
0b6caad
to
bc40797
Compare
Amber::CLI::Spec.cleanup | ||
end | ||
end | ||
describe MainCommand::Encrypt do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any opinion on having this be describe "amber encrypt" do
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See inline comments, the name changes for the describe/context blocks are optional.
If the assert methods are not being used anymore, they should be removed.
|
||
`shards build` | ||
module Amber::CLI | ||
describe MainCommand::Generate do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here - we could have describe "amber generate" do
and remove the context below.
spec/amber/cli/commands/init_spec.cr
Outdated
Amber::CLI::Spec.amber_yml["language"].should eq "slang" | ||
File.read("#{TESTING_APP}/.amber_secret_key").size.should eq 44 | ||
Amber::CLI::Spec.cleanup | ||
describe MainCommand::New do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here, describe "amber new #{TESTING_APP}" do
and remove the context below.
spec/amber/cli/commands/init_spec.cr
Outdated
dirs(TESTING_APP).sort.should eq dirs(APP_TEMPLATE_PATH).sort | ||
end | ||
|
||
describe "-m granite (Granite ORM)" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call this context
but it isn't a deal-breaker.
spec/amber/cli/commands/init_spec.cr
Outdated
Amber::CLI::Spec.db_yml["pg"].should_not be_nil | ||
db_url = Amber::CLI::Spec.db_yml["pg"]["database"].as_s | ||
db_url.should_not be_nil | ||
describe "-m crecto (Crecto Repo)" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing, context
spec/support/helpers/cli_helper.cr
Outdated
def assert_encrypted_files_exists?(enc_file, enc_key) | ||
File.exists?("config/environments/#{enc_file}").should be_true | ||
File.read(enc_key).size.should eq 44 | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these still needed?
4b1088c
to
6023245
Compare
6023245
to
7425718
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be a lot cleaner but didn't spend a ton of time reviewing since its such a large PR.
* Organize Factories into Fixtures * Organizes Helpers into submodules * Cleans up the CLI Commands Specs This organizes and cleans up and DRY the CLI specs making it more readable and cohesive. * Updates * fixup! Organize Factories into Fixtures * fixup! Organize Factories into Fixtures * fixup! Organize Factories into Fixtures
* Organize Factories into Fixtures * Organizes Helpers into submodules * Cleans up the CLI Commands Specs This organizes and cleans up and DRY the CLI specs making it more readable and cohesive. * Updates * fixup! Organize Factories into Fixtures * fixup! Organize Factories into Fixtures * fixup! Organize Factories into Fixtures Former-commit-id: b6f0459
Description of the Change
As the framework grows having a clean and expressive test suite is very important for those who are currently working on the project and new people that want to contribute.
This PR is a WORK IN PROGRESS to clean up and structure the test using the Arrange, Act, Assert Annihilate pattern with only one action and one assertion.
Alternate Designs
Benefits
With the work done it will make it very easy to read and maintain the test suite
Possible Drawbacks