Skip to content
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

Prevent duplicate output #517

Merged
merged 11 commits into from
Feb 7, 2018
Merged

Prevent duplicate output #517

merged 11 commits into from
Feb 7, 2018

Conversation

mvz
Copy link
Contributor

@mvz mvz commented Nov 22, 2017

Summary

Ensure command output is only announced once.

Details

During a run, Command#stop and Command#terminate are called multiple times, among other reasons to ensure all commands are actually terminated at the end of each spec or scenario.

If both general announcers and the announce-on-error functionality is used at the same time, duplicate output may still occur.

This includes changes from #399.

Motivation and Context

This fixes #374.

How Has This Been Tested?

Specs were added by @maxmeyer and myself to ensure stop events are only broadcast once on the event bus. The behavior was confirmed by running some of Aruba's features by hand and examining the entire output produced.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • I've added tests for my code


before :each do
command.start
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Communication: I think this is the "Act" step of Arrange-Act-Assert, and that it's not a before-test setup.

Suggestion: Move command.start into the it.

context '#started' do
before :each do
allow(event_bus).to receive(:notify).with(Events::CommandStarted)
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

before :each => before (this is the default; and it has been renamed in newer versions of RSpec; :each is now :example)

@mvz
Copy link
Contributor Author

mvz commented Nov 22, 2017

@olleolleolle I made the changes you suggested, thanks.

@olleolleolle
Copy link
Contributor

@mvz It's a pleasure to learn so much from the Aruba work you do here.

Copy link
Contributor

@olleolleolle olleolleolle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feature brings clarity to something which can be quite tricky.

@maxmeyer
Copy link
Member

maxmeyer commented Nov 22, 2017

@mvz Thanks for tackling this. Personally I prefer this type of specs, which are more "concise" as they use the Rspec syntax to define readable tests: http://www.betterspecs.org/.

@mvz
Copy link
Contributor Author

mvz commented Nov 23, 2017

@maxmeyer I have two problems with those type of tests:

  • Using subject hides the nature of the object under test. Giving it an expressive name allows you to interpret the expectation itself more easily.
  • Using an anonymous it block makes the intent of the test less clear: Yes, the method has the expected result, but why do we want it to have that result? Also, some desired outcomes cannot be expressed in RSpec syntax (e.g.,`it 'prevents #stop from notifying the event bus').

@olleolleolle
Copy link
Contributor

olleolleolle commented Nov 23, 2017

@mvz In order to have the cake and eat it, explicitly naming the subject allows

let(:command) do
  described_class.new(
    'true',
    event_bus: event_bus,
    exit_timeout: exit_timeout,
    io_wait_timeout: io_wait_timeout,
    working_directory: working_directory,
    environment: environment,
    main_class: main_class,
    stop_signal: stop_signal,
    startup_wait_time: startup_wait_time
  )
end 

to be

subject(:command) do
  described_class.new(
    'true',
    event_bus: event_bus,
    exit_timeout: exit_timeout,
    io_wait_timeout: io_wait_timeout,
    working_directory: working_directory,
    environment: environment,
    main_class: main_class,
    stop_signal: stop_signal,
    startup_wait_time: startup_wait_time
  )
end 

and, taking it a step further, passing the constructor parameters we're not manipulating in the test as primitive values would reduce "setup".

PS: I find the rspec-its does not do very much for the readability of my testing.

@maxmeyer
Copy link
Member

maxmeyer commented Nov 23, 2017

@mvz Sorry, I was not very clear about that. I was a bit in a rush and didn't see, that that use is_expected. I don't like that style either, but try to avoid this.

I try to avoid using strings in the it-method.

RSpec.describe MyClass do
  it 'some description' do
     expect(true).to_be true
  end
end

Instead I try to use something like that:

RSpec.describe MyClass do
  subject(:my_instance) { described_class.new }

  context 'when action was run' do
    # Set state - if required
    before :example do
      my_instance.my_action
    end

    # Assert
     it { expect(my_instance.result).to_be true }
  end
end

I'm open to change the style to something which suits our needs best. But besides that, what I really want to see for our test suite: Use the same style we can commit to everywhere and don't mix styles. Example for the style current used at most places I had a look at: https://github.com/cucumber/aruba/blob/master/spec/aruba/api_spec.rb#L8-L18.

PS: I find the rspec-its does not do very much for the readability of my testing.

@olleolleolle What do you mean with rspec-its

subject(:command) do

Yes, this makes the "sut" explicit.

@mvz
Copy link
Contributor Author

mvz commented Nov 24, 2017

@maxmeyer agreed on having a consistent style. I'll rewrite the examples and see how that goes.

@olleolleolle
Copy link
Contributor

@maxmeyer Hi!

rspec-its is now a separate RubyGem.

Myron Marston wrote this, before its was removed: Explanation for why its will be removed from rspec-3

@maxmeyer
Copy link
Member

maxmeyer commented Nov 24, 2017

@olleolleolle Thanks for clarifying that. Is there any place where we use this kind of style? I searched the repository and didn't find a place where we do this. Did I miss something?

First, I thought http://www.betterspecs.org/ recommends this style, but I can't find anything about rspec-its there either. It's nothing I used before. And reading Myron's writeup makes me thing, this is not a good way to go.

My style of writing RSpec specs was influenced by a talk. I think, it was this one: https://www.youtube.com/watch?v=d2gL6CYaYwQ. Though I don't use the is_expected-syntax for the reasons @mvz wrote down. There's also a later talk on youtube https://www.youtube.com/watch?v=KjENZNjRCWM, but I didn't had a look into it.

The style recommended by this talk helps me to

  • concentrate on the way my code behaves in different contexts - using #context "when something is given"
  • to DRY up my tests - though this goes "against" readability

But as you both are more into testing than me - my daily job is to keep things running as a sysadmin - I think you've got more experience than me and I'm happy to learn new things. 😄

require 'spec_helper'

RSpec.describe Aruba::Command do
let(:command) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed: I prefer to use subject(:command) here.

end

it 'leaves the command in the started state' do
command.start
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would place this in a separate #before-block`.

@olleolleolle
Copy link
Contributor

@maxmeyer Now that we're trading video links, here's Searls, talking (very quickly) about testing:

@stale
Copy link

stale bot commented Jan 23, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in a week if no further activity occurs.

@stale stale bot added the stale These issues were closed by stalebot and need to be reviewed to see if they're still relevant. label Jan 23, 2018
@mvz mvz removed the stale These issues were closed by stalebot and need to be reviewed to see if they're still relevant. label Jan 24, 2018
@mvz mvz force-pushed the issue-374-duplicate-output branch 3 times, most recently from 728cdfa to 6197cdc Compare February 3, 2018 19:38
@mvz
Copy link
Contributor Author

mvz commented Feb 4, 2018

@olleolleolle I updated the specs and added one little fix for the InProcess runner. Can you take one final look at this?

@olleolleolle
Copy link
Contributor

Great! Covering those bits is super good.

Copy link
Contributor

@olleolleolle olleolleolle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s get this merged!

Dennis Günnewig and others added 5 commits February 4, 2018 19:10
If a users decided to use `run_simple`, a command is stopped twice:

1. After the configured wait time
2. On the end of test suite via terminate_all_commands

This makes the output appear twice. This is fixed by this PR. It also
make a method call fail:

1. Command already stopped, `#stop` is called again
2. Comannd has not been started, but ist `#stop`ped
mvz added 6 commits February 4, 2018 19:12
Without this, the command is never stopped and the stop notification is
never broadcast.
- Merge before blocks and remove :each
- Move calls that are part of the specs' Act steps into the it blocks
- Replace context blocks with describe and name the correct method names
@mvz mvz force-pushed the issue-374-duplicate-output branch from 97701b6 to 76b8c47 Compare February 4, 2018 18:13
@mvz mvz merged commit d59217a into master Feb 7, 2018
@mvz mvz deleted the issue-374-duplicate-output branch February 7, 2018 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Prevent duplicating stderr/stdout for run_simple commands
3 participants