[DRE-commits] [ruby-aruba] 39/74: Replace internal event queue with event-bus from library

Hideki Yamane henrich at moszumanska.debian.org
Sat Nov 28 01:16:38 UTC 2015


This is an automated email from the git hooks/post-receive script.

henrich pushed a commit to branch debian/sid
in repository ruby-aruba.

commit 724b9424c453f1013093f9284494753bba68f9d4
Author: Max Meyer <dev at fedux.org>
Date:   Fri Aug 21 16:23:17 2015 +0200

    Replace internal event queue with event-bus from library
---
 Gemfile                                            |   2 +-
 aruba.gemspec                                      |   1 +
 features/api/command/find_command.feature          |  34 +++
 features/api/command/last_command_started.feature  |  50 +++++
 features/api/command/last_command_stopped.feature  |  89 ++++++++
 features/getting_started/run_commands.feature      | 187 ++++++++++++++++
 .../supported_programming_languages.feature        |  89 --------
 .../matchers/file/be_existing_executable.feature   |  87 ++++++++
 .../integration.feature}                           |  31 +++
 lib/aruba.rb                                       |  19 --
 lib/aruba/announcer.rb                             | 219 ------------------
 lib/aruba/api/command.rb                           |  58 +++--
 lib/aruba/api/core.rb                              |  19 +-
 lib/aruba/api/deprecated.rb                        |  25 ++-
 lib/aruba/api/environment.rb                       |  28 ++-
 lib/aruba/api/filesystem.rb                        |  10 +
 lib/aruba/api/text.rb                              |   2 +-
 lib/aruba/basic_configuration.rb                   |   5 +-
 lib/aruba/command.rb                               |  37 +++-
 lib/aruba/config.rb                                |   2 +-
 lib/aruba/config_wrapper.rb                        |  47 +++-
 lib/aruba/console.rb                               |   1 -
 lib/aruba/cucumber/command.rb                      |  11 +-
 lib/aruba/cucumber/file.rb                         |   2 +-
 lib/aruba/cucumber/hooks.rb                        |  65 +++---
 lib/aruba/errors.rb                                |  10 +-
 lib/aruba/events.rb                                |  13 ++
 lib/aruba/events/basic_event.rb                    |  11 +
 lib/aruba/events/command_stopped.rb                |   5 +
 .../{config_wrapper.rb => in_config_wrapper.rb}    |   2 +-
 lib/aruba/matchers/command/have_exit_status.rb     |   2 +-
 .../matchers/command/have_finished_in_time.rb      |  11 +-
 lib/aruba/matchers/command/have_output.rb          |  11 +-
 .../matchers/command/have_output_on_stderr.rb      |  11 +-
 .../matchers/command/have_output_on_stdout.rb      |  11 +-
 .../matchers/file/be_an_existing_executable.rb     |  37 ++++
 lib/aruba/platforms/announcer.rb                   | 221 +++++++++++++++++++
 lib/aruba/{ => platforms}/aruba_logger.rb          |   0
 lib/aruba/platforms/command_monitor.rb             | 244 +++++++++++++++++++++
 lib/aruba/platforms/unix_platform.rb               |  19 +-
 lib/aruba/platforms/unix_which.rb                  |   4 +-
 lib/aruba/platforms/windows_which.rb               |   4 +-
 lib/aruba/process_monitor.rb                       | 201 -----------------
 lib/aruba/processes/basic_process.rb               |   8 +-
 lib/aruba/processes/in_process.rb                  |   2 +-
 lib/aruba/processes/null_process.rb                |  26 ---
 lib/aruba/processes/spawn_process.rb               |  13 +-
 lib/aruba/rspec.rb                                 |  54 +++--
 lib/aruba/runtime.rb                               |  41 +++-
 lib/aruba/setup.rb                                 |  86 ++++++++
 spec/aruba/api_spec.rb                             |  49 ++---
 ...g_wrapper_spec.rb => in_config_wrapper_spec.rb} |   2 +-
 spec/aruba/spawn_process_spec.rb                   |  23 +-
 spec/support/configs/pry.rb                        |   3 +
 spec/support/shared_contexts/aruba.rb              |   1 +
 55 files changed, 1440 insertions(+), 805 deletions(-)

diff --git a/Gemfile b/Gemfile
index f8fb9d6..b5b83ac 100644
--- a/Gemfile
+++ b/Gemfile
@@ -42,7 +42,7 @@ group :development, :test do
   gem 'simplecov', '~> 0.10'
 
   # Test api
-  gem 'rspec', '~> 3.3.0'
+  gem 'rspec', '~> 3.4'
   gem 'fuubar', '~> 2.0.0'
 
   # using platform for this make bundler complain about the same gem given
diff --git a/aruba.gemspec b/aruba.gemspec
index 41c1596..4edcbd2 100644
--- a/aruba.gemspec
+++ b/aruba.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
   s.add_runtime_dependency 'rspec-expectations', '>= 2.99'
   s.add_runtime_dependency 'contracts', '~> 0.9'
   s.add_runtime_dependency 'thor', '~> 0.19'
+  s.add_runtime_dependency 'event-bus', '~> 0.2.0'
 
   s.add_development_dependency 'bundler', '~> 1.10.2'
 
diff --git a/features/api/command/find_command.feature b/features/api/command/find_command.feature
new file mode 100644
index 0000000..ccdeb5d
--- /dev/null
+++ b/features/api/command/find_command.feature
@@ -0,0 +1,34 @@
+Feature: Find a started command
+
+  Scenario: Exising command
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('echo hello') }
+      let(:command) { find_command('echo hello') }
+
+      before(:each) { stop_all_commands }
+
+      it { expect(command).to be_successfully_executed }
+      it { expect(command.commandline).to eq 'echo hello' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Non-Exising command
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      let(:command) { find_command('echo hello') }
+
+      it { expect{ command }.to raise_error Aruba::CommandNotFound }
+      it { expect{ command.commandline }.to raise_error Aruba::CommandNotFound }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
diff --git a/features/api/command/last_command_started.feature b/features/api/command/last_command_started.feature
new file mode 100644
index 0000000..559f103
--- /dev/null
+++ b/features/api/command/last_command_started.feature
@@ -0,0 +1,50 @@
+Feature: Return last command started
+
+  Background:
+    Given I use a fixture named "cli-app"
+
+  Scenario: A command has been started
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('echo hello') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started).to be_successfully_executed }
+      it { expect(last_command_started.commandline).to eq 'echo hello' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Multiple commands have been started
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('echo hello') }
+      before(:each) { run('echo world') }
+
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_started).to be_successfully_executed }
+      it { expect(last_command_started.commandline).to eq 'echo world' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: No command has been started
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      it { expect{ last_command_started.commandline }.to raise_error Aruba::NoCommandHasBeenStartedError }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
diff --git a/features/api/command/last_command_stopped.feature b/features/api/command/last_command_stopped.feature
new file mode 100644
index 0000000..769d617
--- /dev/null
+++ b/features/api/command/last_command_stopped.feature
@@ -0,0 +1,89 @@
+Feature: Return last command stopped
+
+  Background:
+    Given I use a fixture named "cli-app"
+
+  Scenario: A command has been started
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('echo hello') }
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_stopped).to be_successfully_executed }
+      it { expect(last_command_stopped.commandline).to eq 'echo hello' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Multiple commands have been started and all are stopped
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('echo hello') }
+      before(:each) { run('echo world') }
+
+      before(:each) { stop_all_commands }
+
+      it { expect(last_command_stopped).to be_successfully_executed }
+      it { expect(last_command_stopped.commandline).to eq 'echo world' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Multiple commands have been started and a single one is stopped
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('echo hello') }
+      before(:each) { find_command('echo hello').stop }
+      before(:each) { run('echo world') }
+
+      it { expect(last_command_stopped).to be_successfully_executed }
+      it { expect(last_command_stopped.commandline).to eq 'echo hello' }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+
+  @requires-aruba-version-1
+  Scenario: No command has been started
+    Given a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      it { expect{ last_command_stopped.commandline }.to raise_error Aruba::NoCommandHasBeenStoppedError }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  @requires-aruba-version-1
+  Scenario: No command has been stopped
+    Given an executable named "bin/cli" with:
+    """bash
+    #!/bin/bash
+    while [ true ]; do sleep 1; done
+    """
+    And a file named "spec/run_spec.rb" with:
+    """ruby
+    require 'spec_helper'
+
+    RSpec.describe 'Run command', :type => :aruba do
+      before(:each) { run('cli') }
+
+      it { expect{ last_command_stopped.commandline }.to raise_error Aruba::NoCommandHasBeenStoppedError }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
diff --git a/features/getting_started/run_commands.feature b/features/getting_started/run_commands.feature
new file mode 100644
index 0000000..c7da2f8
--- /dev/null
+++ b/features/getting_started/run_commands.feature
@@ -0,0 +1,187 @@
+Feature: Run commands with Aruba
+
+  As long as you've got the neccessary programs, libraries, runtime
+  environments, interpreters installed, it doesn't matter in which programming
+  language your commandline application is implemented. You can even use POSIX
+  standard tools like "printf".
+
+  Below you find some examples of the "Hello, Aruba!"-application implemented
+  with different programming languages and a single example for a POSIX
+  standard tool. This is NOT an exclusive list. Every commandline application
+  should run with `aruba`.
+
+  Background:
+    Given I use a fixture named "getting-started-app"
+    And a file named "features/hello_aruba.feature" with:
+    """
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given I successfully run `cli`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+
+  Scenario: Bash Program
+    Given an executable named "bin/cli" with:
+    """bash
+    #!/usr/bin/env bash
+
+    echo "Hello, Aruba!"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Ruby Program
+    Given an executable named "bin/cli" with:
+    """ruby
+    #!/usr/bin/env ruby
+
+    puts "Hello, Aruba!"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Bash Program run via bash
+    Given a file named "tmp/aruba/bin/cli.sh" with:
+    """bash
+    echo "Hello, Aruba!"
+    """
+    And a file named "features/hello_aruba.feature" with:
+    """
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given I successfully run `bash bin/cli.sh`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Ruby Program
+    Given an executable named "bin/cli" with:
+    """ruby
+    #!/usr/bin/env ruby
+
+    puts "Hello, Aruba!"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Ruby Program via "ruby"
+    Given an executable named "bin/cli.rb" with:
+    """ruby
+    puts "Hello, Aruba!"
+    """
+    And a file named "features/hello_aruba.feature" with:
+    """
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given I successfully run `ruby bin/cli.rb`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Python Program
+    Given an executable named "bin/cli" with:
+    """python
+    #!/usr/bin/env python
+
+    print("Hello, Aruba!")
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Python Program via "python"
+    Given a file named "bin/cli.py" with:
+    """python
+    print("Hello, Aruba!")
+    """
+    And a file named "features/hello_aruba.feature" with:
+    """
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given I successfully run `python bin/cli.py`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Perl Program
+    Given an executable named "bin/cli" with:
+    """perl
+    #!/usr/bin/env perl
+
+    print "Hello, Aruba!\n";
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Perl Program via "perl"
+    Given an executable named "bin/cli.pl" with:
+    """perl
+    print "Hello, Aruba!\n";
+    """
+    And a file named "features/hello_aruba.feature" with:
+    """
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given I successfully run `perl bin/cli.pl`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: Java Program
+
+    It's even possible to compile and run Java programs with Aruba.
+
+    Given a file named "features/hello_aruba.feature" with:
+    """cucumber
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given a file named "tmp/HelloArubaApp.java" with:
+        \"\"\"
+        class HelloArubaApp {
+          public static void main(String[] args) {
+            System.out.println("Hello, Aruba!");
+          }
+        }
+        \"\"\"
+        And I successfully run `javac tmp/HelloArubaApp.java`
+        And I cd to "tmp/"
+        And I successfully run `java HelloArubaApp`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
+
+  Scenario: POSIX standard tools
+    Given a file named "features/hello_aruba.feature" with:
+    """
+    Feature: Getting Started With Aruba
+      Scenario: First Run of Command
+        Given I successfully run `printf "%s" "Hello, Aruba!"`
+        Then the output should contain:
+        \"\"\"
+        Hello, Aruba!
+        \"\"\"
+    """
+    When I successfully run `cucumber`
+    Then the features should all pass
diff --git a/features/getting_started/supported_programming_languages.feature b/features/getting_started/supported_programming_languages.feature
deleted file mode 100644
index d237b7f..0000000
--- a/features/getting_started/supported_programming_languages.feature
+++ /dev/null
@@ -1,89 +0,0 @@
-Feature: Supported programming languages
-
-  As long as you've got the neccessary programs, libraries, runtime
-  environments, interpreters installed, it doesn't matter in which programming
-  language your commandline application is implemented. 
-
-  Below you find some examples of the "Hello, Aruba!"-application implemented
-  with different programming languages. This is NOT an exclusive list. Every
-  commandline application should run with `aruba`.
-
-  Background:
-    Given I use a fixture named "getting-started-app"
-    And a file named "features/hello_aruba.feature" with:
-    """
-    Feature: Getting Started With Aruba
-      Scenario: First Run of Command
-        Given I successfully run `cli`
-        Then the output should contain:
-        \"\"\"
-        Hello, Aruba!
-        \"\"\"
-    """
-
-  Scenario: Bash Program
-    Given an executable named "bin/cli" with:
-    """bash
-    #!/usr/bin/env bash
-
-    echo "Hello, Aruba!"
-    """
-    When I successfully run `cucumber`
-    Then the features should all pass
-
-  Scenario: Ruby Program
-    Given an executable named "bin/cli" with:
-    """ruby
-    #!/usr/bin/env ruby
-
-    puts "Hello, Aruba!"
-    """
-    When I successfully run `cucumber`
-    Then the features should all pass
-
-  Scenario: Python Program
-    Given an executable named "bin/cli" with:
-    """python
-    #!/usr/bin/env python
-
-    print("Hello, Aruba!")
-    """
-    When I successfully run `cucumber`
-    Then the features should all pass
-
-  Scenario: Perl Program
-    Given an executable named "bin/cli" with:
-    """perl
-    #!/usr/bin/env perl
-
-    print "Hello, Aruba!\n";
-    """
-    When I successfully run `cucumber`
-    Then the features should all pass
-
-  Scenario: Java Program
-
-    It's even possible to compile and run Java programs with Aruba.
-
-    Given a file named "features/hello_aruba.feature" with:
-    """cucumber
-    Feature: Getting Started With Aruba
-      Scenario: First Run of Command
-        Given a file named "tmp/HelloArubaApp.java" with:
-        \"\"\"
-        class HelloArubaApp {
-          public static void main(String[] args) {
-            System.out.println("Hello, Aruba!");
-          }
-        }
-        \"\"\"
-        And I successfully run `javac tmp/HelloArubaApp.java`
-        And I cd to "tmp/"
-        And I successfully run `java HelloArubaApp`
-        Then the output should contain:
-        \"\"\"
-        Hello, Aruba!
-        \"\"\"
-    """
-    When I successfully run `cucumber`
-    Then the features should all pass
diff --git a/features/matchers/file/be_existing_executable.feature b/features/matchers/file/be_existing_executable.feature
new file mode 100644
index 0000000..ebeb67b
--- /dev/null
+++ b/features/matchers/file/be_existing_executable.feature
@@ -0,0 +1,87 @@
+Feature: Check if path exists and is an executable file
+
+  If you need to check if a given path exists and is a file, you can use the
+  `be_an_existing_executable`-matcher.
+
+  ```ruby
+  require 'spec_helper'
+
+  RSpec.describe 'Check if file exists and is an executable file', :type => :aruba do
+    let(:file) { 'file.txt' }
+    before(:each) { touch(file) }
+
+    it { expect(file).to be_an_existing_executable }
+  end
+  ```
+
+  Background:
+    Given I use a fixture named "cli-app"
+
+  Scenario: Expect single existing executable file
+    Given a file named "spec/existing_executable_spec.rb" with:
+    """
+    require 'spec_helper'
+
+    RSpec.describe 'Check if file exists and is an executable file', :type => :aruba do
+      let(:file) { 'file.txt' }
+      before(:each) { touch(file) }
+      before(:each) { chmod(0755, file) }
+
+      it { expect(file).to be_an_existing_executable }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Expect single non-existing executable file
+    Given a file named "spec/existing_executable_spec.rb" with:
+    """
+    require 'spec_helper'
+
+    RSpec.describe 'Check if file exists and is an executable file', :type => :aruba do
+      let(:file) { 'file.txt' }
+      it { expect(file).not_to be_an_existing_executable }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Expect multiple existing executable files
+    Given a file named "spec/existing_executable_spec.rb" with:
+    """
+    require 'spec_helper'
+
+    RSpec.describe 'Check if file exists and is an executable file', :type => :aruba do
+      let(:files) { %w(file1.txt file2.txt) }
+
+      before :each do
+        files.each do |f|
+          touch(f)
+          chmod(0755, f)
+        end
+      end
+
+      it { expect(files).to all be_an_existing_executable }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
+
+  Scenario: Expect a least one existing executable file
+    Given a file named "spec/existing_executable_spec.rb" with:
+    """
+    require 'spec_helper'
+
+    RSpec.describe 'Check if file exists and is an executable file', :type => :aruba do
+      let(:files) { %w(file1.txt file2.txt) }
+
+      before :each do
+        touch(files.first)
+        chmod(0755, files.first)
+      end
+
+      it { expect(files).to include an_existing_executable }
+    end
+    """
+    When I run `rspec`
+    Then the specs should all pass
diff --git a/features/integration/rspec/getting_started.feature b/features/rspec/integration.feature
similarity index 84%
rename from features/integration/rspec/getting_started.feature
rename to features/rspec/integration.feature
index 82f19d4..701092a 100644
--- a/features/integration/rspec/getting_started.feature
+++ b/features/rspec/integration.feature
@@ -117,6 +117,35 @@ Feature: Getting started with RSpec and aruba
     When I run `rspec`
     Then the specs should all pass
 
+  Scenario: Setup aruba before use any of it's methods
+
+    From 1.0.0 it will be required, that you setup aruba before you use it.
+
+    Given a file named "spec/spec_helper.rb" with:
+    """
+    require 'aruba/api'
+
+    RSpec.configure do |config|
+      config.include Aruba::Api
+    end
+    """
+    And a file named "spec/getting_started_spec.rb" with:
+    """
+    require 'spec_helper'
+
+    RSpec.describe 'Custom Integration of aruba' do
+      let(:file) { 'file.txt' }
+
+      before(:each) { setup_aruba }
+
+      it { expect(true).to be true }
+    end
+    """
+    And an empty file named "tmp/aruba/garbage.txt"
+    When I run `rspec`
+    Then the specs should all pass
+    And the file "tmp/aruba/garbage.txt" should not exist anymore
+
   Scenario: Fail-safe use if "setup_aruba" is not used
 
     If you forgot to run `setup_aruba` before the first method of aruba is
@@ -125,6 +154,8 @@ Feature: Getting started with RSpec and aruba
     Make sure that you run `setup_aruba` before any method of aruba is used. At
     best before each and every test.
 
+    This will be not supported anymore from 1.0.0 on.
+
     Given a file named "spec/spec_helper.rb" with:
     """
     require 'aruba/api'
diff --git a/lib/aruba.rb b/lib/aruba.rb
index 1769fd8..b9342e8 100644
--- a/lib/aruba.rb
+++ b/lib/aruba.rb
@@ -1,20 +1 @@
-# require 'contracts'
-
-# require 'fileutils'
-# require 'rbconfig'
-# require 'ostruct'
-# require 'pathname'
-
-# require 'aruba/hooks'
-# require 'aruba/basic_configuration'
-# require 'aruba/config_wrapper'
-# require 'aruba/config'
-
-# require 'aruba/announcer'
-# require 'aruba/process_monitor'
-# require 'aruba/runtime'
-
-# require 'aruba/platform'
-# require 'aruba/spawn_process'
-
 require 'aruba/api'
diff --git a/lib/aruba/announcer.rb b/lib/aruba/announcer.rb
deleted file mode 100644
index 03d0be0..0000000
--- a/lib/aruba/announcer.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-require 'shellwords'
-
-module Aruba
-  # Announcer
-  #
-  # @example Activate your you own channel in cucumber
-  #
-  #   Before('@announce-my-channel') do
-  #     announcer.activate :my_channel
-  #   end
-  #
-  # @example Activate your you own channel in rspec > 3
-  #
-  #   before do
-  #     current_example = context.example
-  #     announcer.activate :my_channel if current_example.metadata[:announce_my_channel]
-  #   end
-  #
-  #   Aruba.announcer.announce(:my_channel, 'my message')
-  #
-  class Announcer
-    # Dev null
-    class NullAnnouncer
-      def announce(*)
-        nil
-      end
-
-      def mode?(*)
-        true
-      end
-    end
-
-    # Announcer using Kernel.puts
-    class KernelPutsAnnouncer
-      def announce(message)
-        Kernel.puts message
-      end
-
-      def mode?(m)
-        :kernel_puts == m
-      end
-    end
-
-    # Announcer using Main#puts
-    class PutsAnnouncer
-      def announce(message)
-        Kernel.puts message
-      end
-
-      def mode?(m)
-        :puts == m
-      end
-    end
-
-    private
-
-    attr_reader :announcers, :default_announcer, :announcer, :channels, :output_formats
-
-    public
-
-    def initialize(_, options)
-      @announcers = []
-      @announcers << PutsAnnouncer.new
-      @announcers << KernelPutsAnnouncer.new
-      @announcers << NullAnnouncer.new
-
-      @default_announcer = @announcers.last
-      @announcer         = @announcers.first
-      @channels          = {}
-      @output_formats    = {}
-
-      @options           = options
-
-      after_init
-    end
-
-    private
-
-    # rubocop:disable Metrics/MethodLength
-    def after_init
-      output_format :directory, '$ cd %s'
-      output_format :command, '$ %s'
-      output_format :environment, proc { |n, v| format('$ export %s=%s', n, Shellwords.escape(v)) }
-      output_format :modified_environment, proc { |n, v| format('$ export %s=%s', n, Shellwords.escape(v)) }
-      output_format :full_environment, proc { |h| Aruba.platform.simple_table(h) }
-      output_format :timeout, '# %s-timeout: %s seconds'
-      output_format :wait_time, '# %s: %s seconds'
-      output_format :stop_signal, proc { |p, s| format('Command will be stopped with `kill -%s %s`', s, p) }
-      output_format :stderr, "<<-STDERR\n%s\nSTDERR"
-      output_format :stdout, "<<-STDOUT\n%s\nSTDOUT"
-
-      # rubocop:disable Metrics/LineLength
-      if @options[:stdout]
-        warn('The use of "@announce_stdout-instance" variable and "options[:stdout] = true" for Announcer.new is deprecated. Please use "announcer.activate(:stdout)" instead.')
-        activate :stdout
-      end
-      if @options[:stderr]
-        warn('The use of "@announce_stderr-instance" variable and "options[:stderr] = true" for Announcer.new is deprecated. Please use "announcer.activate(:stderr)" instead.')
-        activate :stderr
-      end
-      if @options[:dir]
-        warn('The use of "@announce_dir-instance" variable and "options[:dir] = true" for Announcer.new is deprecated. Please use "announcer.activate(:directory)" instead.')
-        activate :directory
-      end
-      if @options[:cmd]
-        warn('The use of "@announce_cmd-instance" variable and "options[:cmd] = true" for Announcer.new is deprecated. Please use "announcer.activate(:command)" instead.')
-        activate :command
-      end
-      if @options[:env]
-        warn('The use of "@announce_env-instance" variable and "options[:env] = true" for Announcer.new is deprecated. Please use "announcer.activate(:modified_environment)" instead.')
-        activate :modified_enviroment
-      end
-      # rubocop:enable Metrics/LineLength
-    end
-    # rubocop:enable Metrics/MethodLength
-
-    def output_format(channel, string = '%s', &block)
-      if block_given?
-        output_formats[channel.to_sym] = block
-      elsif  string.is_a?(Proc)
-        output_formats[channel.to_sym] = string
-      else
-        output_formats[channel.to_sym] = proc { |*args| format(string, *args) }
-      end
-
-      self
-    end
-
-    public
-
-    # Reset announcer
-    def reset
-      @default_announcer = @announcers.last
-      @announcer         = @announcers.first
-    end
-
-    # Change mode of announcer
-    #
-    # @param [Symbol] m
-    #   The mode to set
-    def mode=(m)
-      @announcer = @announcers.find { |a| f.mode? m.to_sym }
-
-      self
-    end
-
-    # Check if channel is activated
-    #
-    # @param [Symbol] channel
-    #   The name of the channel to check
-    def activated?(channel)
-      channels[channel.to_sym] == true
-    end
-
-    # Activate a channel
-    #
-    # @param [Symbol] channel
-    #   The name of the channel to activate
-    def activate(channel)
-      channels[channel.to_sym] = true
-
-      self
-    end
-
-    # Announce information to channel
-    #
-    # @param [Symbol] channel
-    #   The name of the channel to check
-    #
-    # @param [Array] args
-    #   Arguments
-    def announce(channel, *args)
-      channel = channel.to_sym
-
-      the_output_format = if output_formats.key? channel
-                            output_formats[channel]
-                          else
-                            proc { |v| format('%s', v) }
-                          end
-
-      message = the_output_format.call(*args)
-
-      announcer.announce(message) if channels[channel]
-
-      default_announcer.announce message
-    end
-
-    # @deprecated
-    def stdout(content)
-      warn('The announcer now has a new api to activate channels. Please use this one: announce(:stdout, message)')
-      announce :stdout, content
-    end
-
-    # @deprecated
-    def stderr(content)
-      warn('The announcer now has a new api to activate channels. Please use this one: announce(:stderr, message)')
-      announce :stderr, content
-    end
-
-    # @deprecated
-    def dir(dir)
-      warn('The announcer now has a new api to activate channels. Please use this one announce(:directory, message)')
-      announce :directory, dir
-    end
-
-    # @deprecated
-    def cmd(cmd)
-      warn('The announcer now has a new api to activate channels. Please use this one announce(:command, message)')
-      announce :command, cmd
-    end
-
-    # @deprecated
-    def env(key, value)
-      warn('The announcer now has a new api to activate channels. Please use this one: announce(:modified_environment, key, value)')
-
-      announce :modified_environment, key, value
-    end
-  end
-end
diff --git a/lib/aruba/api/command.rb b/lib/aruba/api/command.rb
index 45a816e..b1d00a9 100644
--- a/lib/aruba/api/command.rb
+++ b/lib/aruba/api/command.rb
@@ -1,7 +1,6 @@
 require 'pathname'
 
 require 'aruba/platform'
-require 'aruba/process_monitor'
 require 'aruba/command'
 
 # require 'win32/file' if File::ALT_SEPARATOR
@@ -53,31 +52,17 @@ module Aruba
       # @return [Array]
       #   List of commands
       def all_commands
-        process_monitor.all_commands
-      end
-
-      # @private
-      def process_monitor
-        return @process_monitor if defined? @process_monitor
-
-        @process_monitor = ProcessMonitor.new(announcer)
-
-        @process_monitor
-      end
-
-      # @private
-      def processes
-        process_monitor.send(:processes)
+        aruba.command_monitor.registered_commands
       end
 
       # Last command started
       def last_command_started
-        process_monitor.last_command_started
+        aruba.command_monitor.last_command_started
       end
 
       # Last command stopped
       def last_command_stopped
-        process_monitor.last_command_stopped
+        aruba.command_monitor.last_command_stopped
       end
 
       # Stop all commands
@@ -92,7 +77,7 @@ module Aruba
                  all_commands
                end
 
-        cmds.each { |c| c.stop(announcer) }
+        cmds.each(&:stop)
 
         self
       end
@@ -114,6 +99,14 @@ module Aruba
         self
       end
 
+      # Find a started command
+      #
+      # @param [String, Command] commandline
+      #   The commandline
+      def find_command(commandline)
+        aruba.command_monitor.find(commandline)
+      end
+
       # Run given command and stop it if timeout is reached
       #
       # @param [String] cmd
@@ -144,13 +137,13 @@ module Aruba
         environment       = aruba.environment.to_h
         working_directory = expand_path('.')
 
-        announcer.announce(:full_environment, environment)
-        announcer.announce(:timeout, 'exit', exit_timeout)
-        announcer.announce(:timeout, 'io wait', io_wait_timeout)
-        announcer.announce(:wait_time, 'startup wait time', startup_wait_time)
+        aruba.announcer.announce(:full_environment, environment)
+        aruba.announcer.announce(:timeout, 'exit', exit_timeout)
+        aruba.announcer.announce(:timeout, 'io wait', io_wait_timeout)
+        aruba.announcer.announce(:wait_time, 'startup wait time', startup_wait_time)
 
-        announcer.announce(:directory, working_directory)
-        announcer.announce(:command, cmd)
+        aruba.announcer.announce(:directory, working_directory)
+        aruba.announcer.announce(:command, cmd)
 
         cmd               = Aruba.platform.detect_ruby(cmd)
 
@@ -172,7 +165,7 @@ module Aruba
                        aruba.config.main_class
                      end
 
-        command = Command.new(
+        aruba.command_monitor.start_command(
           cmd,
           :mode              => mode,
           :exit_timeout      => exit_timeout,
@@ -184,6 +177,8 @@ module Aruba
           :startup_wait_time => startup_wait_time
         )
 
+        command = aruba.command_monitor.find(cmd)
+
         if aruba.config.before? :cmd
           # rubocop:disable Metrics/LineLength
           Aruba.platform.deprecated('The use of "before"-hook" ":cmd" is deprecated. Use ":command" instead. Please be aware that this hook gets the command passed in not the cmdline itself. To get the commandline use "#cmd.commandline"')
@@ -192,11 +187,9 @@ module Aruba
         end
 
         aruba.config.before(:command, self, command)
-
-        process_monitor.register_process(cmd, command)
         command.start
 
-        announcer.announce(:stop_signal, command.pid, stop_signal) if stop_signal
+        aruba.announcer.announce(:stop_signal, command.pid, stop_signal) if stop_signal
 
         aruba.config.after(:command, self, command)
 
@@ -220,9 +213,12 @@ module Aruba
       #   Timeout for execution
       def run_simple(cmd, fail_on_error = true, exit_timeout = nil, io_wait_timeout = nil)
         command = run(cmd, exit_timeout, io_wait_timeout)
-        @last_exit_status = process_monitor.stop_process(command)
+        command.stop
 
-        @timed_out = command.timed_out?
+        if Aruba::VERSION < '1'
+          @last_exit_status = command.exit_status
+          @timed_out = command.timed_out?
+        end
 
         if fail_on_error
           expect(command).to have_finished_in_time
diff --git a/lib/aruba/api/core.rb b/lib/aruba/api/core.rb
index c69487f..2104123 100644
--- a/lib/aruba/api/core.rb
+++ b/lib/aruba/api/core.rb
@@ -1,10 +1,9 @@
 require 'rspec/expectations'
-require 'aruba/announcer'
 require 'aruba/runtime'
 require 'aruba/errors'
+require 'aruba/setup'
 
 require 'aruba/config/jruby'
-require 'aruba/aruba_logger'
 
 module Aruba
   module Api
@@ -25,9 +24,7 @@ module Aruba
       # artifacts of your tests. This does NOT clean up the current working
       # directory.
       def setup_aruba
-        Aruba.platform.rm File.join(Aruba.config.root_directory, Aruba.config.working_directory), :force => true
-        Aruba.platform.mkdir File.join(Aruba.config.root_directory, Aruba.config.working_directory)
-        Aruba.platform.chdir Aruba.config.root_directory
+        Aruba::Setup.new(aruba).call
 
         self
       end
@@ -52,8 +49,11 @@ module Aruba
           begin
             fail ArgumentError, "#{expand_path(dir)} is not a directory or does not exist." unless Aruba.platform.directory? expand_path(dir)
 
+            old_directory = expand_path('.')
             aruba.current_directory << dir
-            announcer.announce :directory, expand_path(dir)
+            new_directory = expand_path('.')
+
+            aruba.event_bus.notify Events::ChangedWorkingDirectory.new(:old => old_directory, :new => new_directory)
 
             old_dir    = Aruba.platform.getwd
 
@@ -74,8 +74,11 @@ module Aruba
 
         fail ArgumentError, "#{expand_path(dir)} is not a directory or does not exist." unless Aruba.platform.directory? expand_path(dir)
 
+        old_directory = expand_path('.')
         aruba.current_directory << dir
-        announcer.announce :directory, expand_path(dir)
+        new_directory = expand_path('.')
+
+        aruba.event_bus.notify Events::ChangedWorkingDirectory.new(:old => old_directory, :new => new_directory)
 
         self
       end
@@ -170,7 +173,7 @@ module Aruba
       #   The variables to be used for block.
       #
       # @yield
-      #   The block of code which should be run with the modified environment variables
+      #   The block of code which should be run with the changed environment variables
       def with_environment(env = {}, &block)
         old_aruba_env = aruba.environment.to_h
 
diff --git a/lib/aruba/api/deprecated.rb b/lib/aruba/api/deprecated.rb
index 3e788e2..623a26c 100644
--- a/lib/aruba/api/deprecated.rb
+++ b/lib/aruba/api/deprecated.rb
@@ -1,3 +1,5 @@
+require 'aruba/platforms/announcer'
+
 module Aruba
   module Api
     module Deprecated
@@ -376,7 +378,7 @@ module Aruba
       #   The variables to be used for block.
       #
       # @yield
-      #   The block of code which should be run with the modified environment variables
+      #   The block of code which should be run with the changed environment variables
       def with_env(env = {}, &block)
         Aruba.platform.deprecated('The use of "#with_env" is deprecated. Use "#with_environment {}" instead. But be careful this uses a different implementation')
 
@@ -415,8 +417,9 @@ module Aruba
       def set_env(key, value)
         Aruba.platform.deprecated('The use of "#set_env" is deprecated. Please use "set_environment_variable" instead. But be careful, this method uses a different kind of implementation')
 
-        announcer.announce(:environment, key, value)
+        aruba.announcer.announce(:environment, key, value)
         set_environment_variable key, value
+
         original_env[key] = ENV.delete(key) unless original_env.key? key
         ENV[key] = value
       end
@@ -879,9 +882,9 @@ module Aruba
       #
       # Access to announcer
       def announcer
-        # Aruba.platform.deprecated('The use of "#announcer" is deprecated. Use "aruba.announcer" instead')
+        Aruba.platform.deprecated('The use of "#announcer" is deprecated. Use "aruba.announcer" instead')
 
-        @announcer ||= Announcer.new(
+        @announcer ||= Platforms::Announcer.new(
           self,
           :stdout => defined?(@announce_stdout),
           :stderr => defined?(@announce_stderr),
@@ -892,6 +895,20 @@ module Aruba
 
         @announcer
       end
+
+      # @private
+      def process_monitor
+        Aruba.platform.deprecated('The use of "#process_monitor" is deprecated.')
+
+        aruba.command_monitor
+      end
+
+      # @private
+      def processes
+        Aruba.platform.deprecated('The use of "#process_monitor" is deprecated. Please use "#all_commands" instead.')
+
+        aruba.command_monitor.send(:processes)
+      end
     end
   end
 end
diff --git a/lib/aruba/api/environment.rb b/lib/aruba/api/environment.rb
index 3afc7f6..6bfd3fd 100644
--- a/lib/aruba/api/environment.rb
+++ b/lib/aruba/api/environment.rb
@@ -6,7 +6,7 @@ module Aruba
     module Environment
       # Set environment variable
       #
-      # @param [String] key
+      # @param [String] name
       #   The name of the environment variable as string, e.g. 'HOME'
       #
       # @param [String] value
@@ -15,17 +15,18 @@ module Aruba
         name = name.to_s
         value = value.to_s
 
-        announcer.announce(:environment, name, value)
-        announcer.announce(:modified_environment, name, value)
-
+        old_environment = aruba.environment.to_h
         aruba.environment[name] = value
+        new_environment = aruba.environment.to_h
+
+        aruba.event_bus.notify Events::AddedEnvironmentVariable.new(:old => old_environment, :new => new_environment, :changed => { :name => name, :value => value })
 
         self
       end
 
       # Append environment variable
       #
-      # @param [String] key
+      # @param [String] name
       #   The name of the environment variable as string, e.g. 'HOME'
       #
       # @param [String] value
@@ -34,16 +35,18 @@ module Aruba
         name = name.to_s
         value = value.to_s
 
+        old_environment = aruba.environment.to_h
         aruba.environment.append name, value
-        announcer.announce(:environment, name, aruba.environment[name])
-        announcer.announce(:modified_environment, name, aruba.environment[name])
+        new_environment = aruba.environment.to_h
+
+        aruba.event_bus.notify Events::ChangedEnvironmentVariable.new(:old => old_environment, :new => new_environment, :changed => { :name => name, :value => value })
 
         self
       end
 
       # Prepend environment variable
       #
-      # @param [String] key
+      # @param [String] name
       #   The name of the environment variable as string, e.g. 'HOME'
       #
       # @param [String] value
@@ -52,9 +55,11 @@ module Aruba
         name = name.to_s
         value = value.to_s
 
+        old_environment = aruba.environment.to_h
         aruba.environment.prepend name, value
-        announcer.announce(:environment, name, aruba.environment[name])
-        announcer.announce(:modified_environment, name, aruba.environment[name])
+        new_environment = aruba.environment.to_h
+
+        aruba.event_bus.notify Events::ChangedEnvironmentVariable.new(:old => old_environment, :new => new_environment, :changed => { :name => name, :value => value })
 
         self
       end
@@ -69,8 +74,7 @@ module Aruba
       def delete_environment_variable(name)
         name = name.to_s
 
-        announcer.announce(:environment, name, '')
-        announcer.announce(:modified_environment, name, '')
+        aruba.event_bus.notify Events::DeletedEnvironmentVariable.new(:old => old_environment, :new => new_environment, :changed => { :name => name, :value => '' })
 
         aruba.environment.delete name
 
diff --git a/lib/aruba/api/filesystem.rb b/lib/aruba/api/filesystem.rb
index a129aaa..905e810 100644
--- a/lib/aruba/api/filesystem.rb
+++ b/lib/aruba/api/filesystem.rb
@@ -35,6 +35,16 @@ module Aruba
         Aruba.platform.directory? expand_path(file)
       end
 
+      # Check if file exist and is executable
+      #
+      # @param [String] file
+      #   The file which should exist
+      def executable?(path)
+        path =  expand_path(path)
+
+        Aruba.platform.file?(path) && Aruba.platform.executable?(path)
+      end
+
       # Check if path is absolute
       #
       # @return [TrueClass, FalseClass]
diff --git a/lib/aruba/api/text.rb b/lib/aruba/api/text.rb
index 86b78b7..1ddb62b 100644
--- a/lib/aruba/api/text.rb
+++ b/lib/aruba/api/text.rb
@@ -41,7 +41,7 @@ module Aruba
       #
       # Replace variables in command string
       def replace_variables(text)
-        text = text.gsub(/<pid-last-command-started>/, last_command_started.pid.to_s)
+        text = text.gsub(/<pid-last-command-started>/, last_command_started.pid.to_s) if text.include? '<pid-last-command-started>'
 
         text
       end
diff --git a/lib/aruba/basic_configuration.rb b/lib/aruba/basic_configuration.rb
index 35801cd..79cbe72 100644
--- a/lib/aruba/basic_configuration.rb
+++ b/lib/aruba/basic_configuration.rb
@@ -1,5 +1,6 @@
 require 'contracts'
 require 'aruba/basic_configuration/option'
+require 'aruba/in_config_wrapper'
 
 module Aruba
   # Basic configuration for ProxyPacRb
@@ -19,7 +20,7 @@ module Aruba
         fail ArgumentError, 'contract-options is required' if contract.nil?
 
         Contract contract
-        add_option(name, block_given? ? yield(ConfigWrapper.new(known_options)) : default)
+        add_option(name, block_given? ? yield(InConfigWrapper.new(known_options)) : default)
 
         define_method(name) { find_option(name).value }
 
@@ -36,7 +37,7 @@ module Aruba
         fail ArgumentError, 'contract-options is required' if contract.nil?
 
         # Add writer
-        add_option(name, block_given? ? yield(ConfigWrapper.new(known_options)) : default)
+        add_option(name, block_given? ? yield(InConfigWrapper.new(known_options)) : default)
 
         Contract contract
         define_method("#{name}=") { |v| find_option(name).value = v }
diff --git a/lib/aruba/command.rb b/lib/aruba/command.rb
index 13b360c..7a1ecbe 100644
--- a/lib/aruba/command.rb
+++ b/lib/aruba/command.rb
@@ -1,14 +1,21 @@
+require 'delegate'
 require 'aruba/processes/spawn_process'
 require 'aruba/processes/in_process'
 require 'aruba/processes/debug_process'
 
 module Aruba
   class Command < SimpleDelegator
+    private
+
+    attr_reader :event_bus
+
+    public
+
+    # rubocop:disable Metrics/MethodLength
     def initialize(command, opts = {})
       launchers = []
       launchers << Processes::DebugProcess
       launchers << Processes::InProcess
-      launchers << Processes::NullProcess
       launchers << Processes::SpawnProcess
 
       launcher = launchers.find { |l| l.match? opts[:mode] }
@@ -23,8 +30,36 @@ module Aruba
         opts.fetch(:stop_signal),
         opts.fetch(:startup_wait_time)
       )
+
+      @event_bus = opts.fetch(:event_bus)
     rescue KeyError => e
       raise ArgumentError, e.message
     end
+    # rubocop:enable Metrics/MethodLength
+
+    # Stop command
+    def stop(*)
+      __getobj__.stop
+      event_bus.notify Events::CommandStopped.new(self)
+
+      self
+    end
+
+    # Terminate command
+    def terminate(*)
+      __getobj__.terminate
+      event_bus.notify Events::CommandStopped.new(self)
+
+      self
+    end
+
+    # Start command
+    def start
+      __getobj__.start
+      event_bus.notify Events::CommandStarted.new(self)
+
+      self
+    end
+    alias_method :run!, :start
   end
 end
diff --git a/lib/aruba/config.rb b/lib/aruba/config.rb
index e01a2b5..eb92bc7 100644
--- a/lib/aruba/config.rb
+++ b/lib/aruba/config.rb
@@ -2,7 +2,7 @@ require 'contracts'
 
 require 'aruba/version'
 require 'aruba/basic_configuration'
-require 'aruba/config_wrapper'
+require 'aruba/in_config_wrapper'
 require 'aruba/hooks'
 
 require 'aruba/contracts/relative_path'
diff --git a/lib/aruba/config_wrapper.rb b/lib/aruba/config_wrapper.rb
index 43c7d3c..59cc100 100644
--- a/lib/aruba/config_wrapper.rb
+++ b/lib/aruba/config_wrapper.rb
@@ -1,17 +1,48 @@
 module Aruba
+  # This wraps the current runtime configuration of aruba.
+  # If an option is changed, it notifies the event queue.
   class ConfigWrapper
-    attr_reader :config
-    private :config
+    private
 
-    def initialize(config)
-      @config = config.dup
+    attr_reader :config, :event_bus
+
+    public
+
+    # Create proxy
+    #
+    # @param [Config] config
+    #   An aruba config object.
+    #
+    # @param [#notify] event_bus
+    #   The event queue which should be notified.
+    def initialize(config, event_bus)
+      @config      = config
+      @event_bus = event_bus
+    end
+
+    # Proxy all methods
+    #
+    # If one method ends with "=", e.g. ":option1=", then notify the event
+    # queue, that the user changes the value of "option1"
+    def method_missing(name, *args, &block)
+      event_bus.notify Events::ChangedConfiguration.new(:changed => { :name => name.to_s.gsub(/=$/, ''), :value => args.first }) if name.to_s.end_with? '='
+
+      config.send(name, *args, &block)
+    end
+
+    # Pass on respond_to?-calls
+    def respond_to_missing?(name, _include_private)
+      config.respond_to? name
     end
 
-    def method_missing(name, *args)
-      fail ArgumentError, 'Options take no argument' if args.count > 0
-      fail UnknownOptionError, %(Option "#{name}" is unknown. Please use only earlier defined options) unless config.key? name
+    # Compare
+    def ==(other)
+      config == other
+    end
 
-      config[name]
+    # Pass on respond_to?-calls
+    def respond_to?(m)
+      config.respond_to? m
     end
   end
 end
diff --git a/lib/aruba/console.rb b/lib/aruba/console.rb
index bdfaa01..39ec7e3 100644
--- a/lib/aruba/console.rb
+++ b/lib/aruba/console.rb
@@ -17,7 +17,6 @@ module Aruba
       IRB.conf[:PROMPT] = {}
       IRB.conf[:PROMPT][:ARUBA] = {
         :PROMPT_I => '%N:%03n:%i> ',
-        :PROMPT_N => '%N:%03n:%i> ',
         :PROMPT_S => '%N:%03n:%i%l ',
         :PROMPT_C => '%N:%03n:%i* ',
         :RETURN => "# => %s\n"
diff --git a/lib/aruba/cucumber/command.rb b/lib/aruba/cucumber/command.rb
index 8365023..99af54a 100644
--- a/lib/aruba/cucumber/command.rb
+++ b/lib/aruba/cucumber/command.rb
@@ -107,9 +107,6 @@ When(/^I stop the command(?: started last)? if (output|stdout|stderr) contains:$
     end
   rescue ChildProcess::TimeoutError, TimeoutError
     last_command_started.terminate
-  ensure
-    announcer.announce :stdout, last_command_started.stdout
-    announcer.announce :stderr, last_command_started.stderr
   end
 end
 
@@ -158,7 +155,7 @@ Then(/^(?:the )?(output|stderr|stdout)(?: from "([^"]*)")? should( not)? contain
             end
 
   commands = if cmd
-               [process_monitor.get_process(Aruba.platform.detect_ruby(cmd))]
+               [aruba.command_monitor.find(Aruba.platform.detect_ruby(cmd))]
              else
                all_commands
              end
@@ -171,7 +168,7 @@ Then(/^(?:the )?(output|stderr|stdout)(?: from "([^"]*)")? should( not)? contain
 
   if Aruba::VERSION < '1.0'
     combined_output = commands.map do |c|
-      c.stop(announcer)
+      c.stop
       c.send(channel.to_sym).chomp
     end.join("\n")
 
@@ -206,7 +203,7 @@ Then(/^(?:the )?(output|stderr|stdout)(?: from "([^"]*)")? should( not)? contain
             end
 
   commands = if cmd
-               [process_monitor.get_process(Aruba.platform.detect_ruby(cmd))]
+               [aruba.command_monitor.find(Aruba.platform.detect_ruby(cmd))]
              else
                all_commands
              end
@@ -219,7 +216,7 @@ Then(/^(?:the )?(output|stderr|stdout)(?: from "([^"]*)")? should( not)? contain
 
   if Aruba::VERSION < '1.0'
     combined_output = commands.map do |c|
-      c.stop(announcer)
+      c.stop
       c.send(channel.to_sym).chomp
     end.join("\n")
 
diff --git a/lib/aruba/cucumber/file.rb b/lib/aruba/cucumber/file.rb
index db43ea4..682c81e 100644
--- a/lib/aruba/cucumber/file.rb
+++ b/lib/aruba/cucumber/file.rb
@@ -88,7 +88,7 @@ Then(/^the following files should (not )?exist:$/) do |negated, files|
   end
 end
 
-Then(/^(?:a|the) file(?: named)? "([^"]*)" should (not )?exist$/) do |file, expect_match|
+Then(/^(?:a|the) file(?: named)? "([^"]*)" should (not )?exist(?: anymore)?$/) do |file, expect_match|
   if expect_match
     expect(file).not_to be_an_existing_file
   else
diff --git a/lib/aruba/cucumber/hooks.rb b/lib/aruba/cucumber/hooks.rb
index 8091af4..8be15d1 100644
--- a/lib/aruba/cucumber/hooks.rb
+++ b/lib/aruba/cucumber/hooks.rb
@@ -21,7 +21,7 @@ end
 After do
   restore_env
   terminate_all_commands
-  process_monitor.clear
+  aruba.command_monitor.clear
 end
 
 Before('~@no-clobber') do
@@ -29,85 +29,92 @@ Before('~@no-clobber') do
 end
 
 Before('@puts') do
-  announcer.mode = :puts
+  aruba.announcer.mode = :puts
 end
 
 Before('@announce-command') do
-  announcer.activate :command
+  aruba.announcer.activate :command
 end
 
 Before('@announce-cmd') do
   Aruba.platform.deprecated 'The use of "@announce-cmd"-hook is deprecated. Please use "@announce-command"'
 
-  announcer.activate :command
+  aruba.announcer.activate :command
 end
 
 Before('@announce-output') do
-  announcer.activate :stdout
-  announcer.activate :stderr
+  aruba.announcer.activate :stdout
+  aruba.announcer.activate :stderr
 end
 
 Before('@announce-stdout') do
-  announcer.activate :stdout
+  aruba.announcer.activate :stdout
 end
 
 Before('@announce-stderr') do
-  announcer.activate :stderr
+  aruba.announcer.activate :stderr
 end
 
 Before('@announce-dir') do
   Aruba.platform.deprecated 'The use of "@announce-dir"-hook is deprecated. Please use "@announce-directory"'
 
-  announcer.activate :directory
+  aruba.announcer.activate :directory
 end
 
 Before('@announce-directory') do
-  announcer.activate :directory
+  aruba.announcer.activate :directory
 end
 
 Before('@announce-stop-signal') do
-  announcer.activate :stop_signal
+  aruba.announcer.activate :stop_signal
 end
 
 Before('@announce-env') do
-  Aruba.platform.deprecated 'The use of "@announce-env"-hook is deprecated. Please use "@announce-modified-environment"'
+  Aruba.platform.deprecated 'The use of "@announce-env"-hook is deprecated. Please use "@announce-changed-environment"'
 
-  announcer.activate :environment
+  aruba.announcer.activate :environment
 end
 
 Before('@announce-environment') do
-  Aruba.platform.deprecated '@announce-environment is deprecated. Use @announce-modified-environment instead'
+  Aruba.platform.deprecated '@announce-environment is deprecated. Use @announce-changed-environment instead'
 
-  announcer.activate :modified_environment
+  aruba.announcer.activate :changed_environment
 end
 
 Before('@announce-full-environment') do
-  announcer.activate :full_environment
+  aruba.announcer.activate :full_environment
 end
 
 Before('@announce-modified-environment') do
-  announcer.activate :modified_environment
+  Aruba.platform.deprecated '@announce-modified-environment is deprecated. Use @announce-changed-environment instead'
+
+  aruba.announcer.activate :changed_environment
+end
+
+Before('@announce-changed-environment') do
+  aruba.announcer.activate :changed_environment
 end
 
 Before('@announce-timeout') do
-  announcer.activate :timeout
+  aruba.announcer.activate :timeout
 end
 
 Before('@announce-wait-time') do
-  announcer.activate :wait_time
+  aruba.announcer.activate :wait_time
 end
 
 Before('@announce') do
-  announcer.activate :command
-  announcer.activate :stdout
-  announcer.activate :stderr
-  announcer.activate :directory
-  announcer.activate :modified_environment
-  announcer.activate :full_environment
-  announcer.activate :environment
-  announcer.activate :timeout
-  announcer.activate :wait_time
-  announcer.activate :stop_signal
+  aruba.announcer.activate :changed_environment
+  aruba.announcer.activate :command
+  aruba.announcer.activate :directory
+  aruba.announcer.activate :environment
+  aruba.announcer.activate :full_environment
+  aruba.announcer.activate :modified_environment
+  aruba.announcer.activate :stderr
+  aruba.announcer.activate :stdout
+  aruba.announcer.activate :stop_signal
+  aruba.announcer.activate :timeout
+  aruba.announcer.activate :wait_time
 end
 
 Before('@debug') do
diff --git a/lib/aruba/errors.rb b/lib/aruba/errors.rb
index 26698e7..2e2c6d9 100644
--- a/lib/aruba/errors.rb
+++ b/lib/aruba/errors.rb
@@ -11,6 +11,14 @@ module Aruba
   # Raised if one tries to use an unknown configuration option
   class UnknownOptionError < ArgumentError; end
 
-  # Rais if command already died
+  # Raised if command already died
   class CommandAlreadyStoppedError < Error; end
+
+  # Raised if one tries to access last command started, but no command
+  # has been started
+  class NoCommandHasBeenStartedError < StandardError; end
+
+  # Raised if one tries to access last command stopped, but no command
+  # has been stopped
+  class NoCommandHasBeenStoppedError < StandardError; end
 end
diff --git a/lib/aruba/events.rb b/lib/aruba/events.rb
new file mode 100644
index 0000000..ff111bd
--- /dev/null
+++ b/lib/aruba/events.rb
@@ -0,0 +1,13 @@
+require 'aruba/events/basic_event'
+
+module Aruba
+  module Events
+    class CommandStopped < BasicEvent; end
+    class CommandStarted < BasicEvent; end
+    class ChangedEnvironmentVariable < BasicEvent; end
+    class AddedEnvironmentVariable < BasicEvent; end
+    class DeletedEnvironmentVariable < BasicEvent; end
+    class ChangedWorkingDirectory < BasicEvent; end
+    class ChangedConfiguration < BasicEvent; end
+  end
+end
diff --git a/lib/aruba/events/basic_event.rb b/lib/aruba/events/basic_event.rb
new file mode 100644
index 0000000..ed2b61f
--- /dev/null
+++ b/lib/aruba/events/basic_event.rb
@@ -0,0 +1,11 @@
+module Aruba
+  module Events
+    class BasicEvent
+      attr_reader :entity
+
+      def initialize(entity)
+        @entity = entity
+      end
+    end
+  end
+end
diff --git a/lib/aruba/events/command_stopped.rb b/lib/aruba/events/command_stopped.rb
new file mode 100644
index 0000000..bba306f
--- /dev/null
+++ b/lib/aruba/events/command_stopped.rb
@@ -0,0 +1,5 @@
+module Aruba
+  module Events
+    class CommandStopped < BasicEvent; end
+  end
+end
diff --git a/lib/aruba/config_wrapper.rb b/lib/aruba/in_config_wrapper.rb
similarity index 94%
copy from lib/aruba/config_wrapper.rb
copy to lib/aruba/in_config_wrapper.rb
index 43c7d3c..05217fb 100644
--- a/lib/aruba/config_wrapper.rb
+++ b/lib/aruba/in_config_wrapper.rb
@@ -1,5 +1,5 @@
 module Aruba
-  class ConfigWrapper
+  class InConfigWrapper
     attr_reader :config
     private :config
 
diff --git a/lib/aruba/matchers/command/have_exit_status.rb b/lib/aruba/matchers/command/have_exit_status.rb
index 8ba2963..05d9db6 100644
--- a/lib/aruba/matchers/command/have_exit_status.rb
+++ b/lib/aruba/matchers/command/have_exit_status.rb
@@ -20,7 +20,7 @@ RSpec::Matchers.define :have_exit_status do |expected|
   match do |actual|
     @old_actual = actual
 
-    @old_actual.stop(announcer) unless @old_actual.stopped?
+    @old_actual.stop unless @old_actual.stopped?
     @actual = actual.exit_status
 
     next false unless @old_actual.respond_to? :exit_status
diff --git a/lib/aruba/matchers/command/have_finished_in_time.rb b/lib/aruba/matchers/command/have_finished_in_time.rb
index 9286a36..e02bd21 100644
--- a/lib/aruba/matchers/command/have_finished_in_time.rb
+++ b/lib/aruba/matchers/command/have_finished_in_time.rb
@@ -26,16 +26,7 @@ RSpec::Matchers.define :have_finished_in_time do
 
     next false unless @old_actual.respond_to? :timed_out?
 
-    @announcer ||= Aruba::Announcer.new(
-      self,
-      :stdout => @announce_stdout,
-      :stderr => @announce_stderr,
-      :dir    => @announce_dir,
-      :cmd    => @announce_cmd,
-      :env    => @announce_env
-    )
-
-    @old_actual.stop(@announcer) unless @old_actual.stopped?
+    @old_actual.stop unless @old_actual.stopped?
 
     @old_actual.timed_out? == false
   end
diff --git a/lib/aruba/matchers/command/have_output.rb b/lib/aruba/matchers/command/have_output.rb
index 5e1d357..d284f58 100644
--- a/lib/aruba/matchers/command/have_output.rb
+++ b/lib/aruba/matchers/command/have_output.rb
@@ -19,16 +19,7 @@ RSpec::Matchers.define :have_output do |expected|
 
     next false unless @old_actual.respond_to? :output
 
-    @announcer ||= Aruba::Announcer.new(
-      self,
-      :stdout => @announce_stdout,
-      :stderr => @announce_stderr,
-      :dir    => @announce_dir,
-      :cmd    => @announce_cmd,
-      :env    => @announce_env
-    )
-
-    @old_actual.stop(@announcer)
+    @old_actual.stop
 
     @actual = sanitize_text(actual.output)
 
diff --git a/lib/aruba/matchers/command/have_output_on_stderr.rb b/lib/aruba/matchers/command/have_output_on_stderr.rb
index a4991be..2bb846d 100644
--- a/lib/aruba/matchers/command/have_output_on_stderr.rb
+++ b/lib/aruba/matchers/command/have_output_on_stderr.rb
@@ -19,16 +19,7 @@ RSpec::Matchers.define :have_output_on_stderr do |expected|
 
     next false unless @old_actual.respond_to? :stderr
 
-    @announcer ||= Aruba::Announcer.new(
-      self,
-      :stdout => @announce_stdout,
-      :stderr => @announce_stderr,
-      :dir    => @announce_dir,
-      :cmd    => @announce_cmd,
-      :env    => @announce_env
-    )
-
-    @old_actual.stop(@announcer) unless @old_actual.stopped?
+    @old_actual.stop unless @old_actual.stopped?
 
     @actual = sanitize_text(actual.stderr)
 
diff --git a/lib/aruba/matchers/command/have_output_on_stdout.rb b/lib/aruba/matchers/command/have_output_on_stdout.rb
index 90b1092..7f70e5f 100644
--- a/lib/aruba/matchers/command/have_output_on_stdout.rb
+++ b/lib/aruba/matchers/command/have_output_on_stdout.rb
@@ -19,16 +19,7 @@ RSpec::Matchers.define :have_output_on_stdout do |expected|
 
     next false unless @old_actual.respond_to? :stdout
 
-    @announcer ||= Aruba::Announcer.new(
-      self,
-      :stdout => @announce_stdout,
-      :stderr => @announce_stderr,
-      :dir    => @announce_dir,
-      :cmd    => @announce_cmd,
-      :env    => @announce_env
-    )
-
-    @old_actual.stop(@announcer) unless @old_actual.stopped?
+    @old_actual.stop unless @old_actual.stopped?
 
     @actual = sanitize_text(actual.stdout)
 
diff --git a/lib/aruba/matchers/file/be_an_existing_executable.rb b/lib/aruba/matchers/file/be_an_existing_executable.rb
new file mode 100644
index 0000000..b34612b
--- /dev/null
+++ b/lib/aruba/matchers/file/be_an_existing_executable.rb
@@ -0,0 +1,37 @@
+require 'rspec/expectations/version'
+require 'shellwords'
+
+# @!method be_an_existing_executable
+#   This matchers checks if <file> exists in filesystem
+#
+#   @return [TrueClass, FalseClass] The result
+#
+#     false:
+#     * if file does not exist
+#     true:
+#     * if file exists
+#
+#   @example Use matcher
+#
+#     RSpec.describe do
+#       it { expect(file1).to be_an_existing_executable }
+#     end
+RSpec::Matchers.define :be_an_existing_executable do |_|
+  match do |actual|
+    @actual = Shellwords.split(actual.commandline).first if actual.respond_to? :commandline
+
+    executable?(@actual)
+  end
+
+  failure_message do |actual|
+    format("expected that executable \"%s\" exists", actual)
+  end
+
+  failure_message_when_negated do |actual|
+    format("expected that executable \"%s\" does not exist", actual)
+  end
+end
+
+if RSpec::Expectations::Version::STRING >= '3.0'
+  RSpec::Matchers.alias_matcher :an_existing_executable, :be_an_existing_executable
+end
diff --git a/lib/aruba/platforms/announcer.rb b/lib/aruba/platforms/announcer.rb
new file mode 100644
index 0000000..15118c8
--- /dev/null
+++ b/lib/aruba/platforms/announcer.rb
@@ -0,0 +1,221 @@
+require 'shellwords'
+
+module Aruba
+  module Platforms
+    # Announcer
+    #
+    # @example Activate your you own channel in cucumber
+    #
+    #   Before('@announce-my-channel') do
+    #     aruba.announcer.activate :my_channel
+    #   end
+    #
+    # @example Activate your you own channel in rspec > 3
+    #
+    #   before do
+    #     current_example = context.example
+    #     aruba.announcer.activate :my_channel if current_example.metadata[:announce_my_channel]
+    #   end
+    #
+    #   Aruba.announcer.announce(:my_channel, 'my message')
+    #
+    class Announcer
+      # Dev null
+      class NullAnnouncer
+        def announce(*)
+          nil
+        end
+
+        def mode?(*)
+          true
+        end
+      end
+
+      # Announcer using Kernel.puts
+      class KernelPutsAnnouncer
+        def announce(message)
+          Kernel.puts message
+        end
+
+        def mode?(m)
+          :kernel_puts == m
+        end
+      end
+
+      # Announcer using Main#puts
+      class PutsAnnouncer
+        def announce(message)
+          Kernel.puts message
+        end
+
+        def mode?(m)
+          :puts == m
+        end
+      end
+
+      private
+
+      attr_reader :announcers, :default_announcer, :announcer, :channels, :output_formats
+
+      public
+
+      def initialize(*args)
+        @announcers = []
+        @announcers << PutsAnnouncer.new
+        @announcers << KernelPutsAnnouncer.new
+        @announcers << NullAnnouncer.new
+
+        @default_announcer = @announcers.last
+        @announcer         = @announcers.first
+        @channels          = {}
+        @output_formats    = {}
+
+        @options           = args[1] || {}
+
+        after_init
+      end
+
+      private
+
+      # rubocop:disable Metrics/MethodLength
+      def after_init
+        output_format :changed_configuration, proc { |n, v| format('# %s = %s', n, v) }
+        output_format :changed_environment, proc { |n, v| format('$ export %s=%s', n, Shellwords.escape(v)) }
+        output_format :command, '$ %s'
+        output_format :directory, '$ cd %s'
+        output_format :environment, proc { |n, v| format('$ export %s=%s', n, Shellwords.escape(v)) }
+        output_format :full_environment, proc { |h| Aruba.platform.simple_table(h) }
+        output_format :modified_environment, proc { |n, v| format('$ export %s=%s', n, Shellwords.escape(v)) }
+        output_format :stderr, "<<-STDERR\n%s\nSTDERR"
+        output_format :stdout, "<<-STDOUT\n%s\nSTDOUT"
+        output_format :stop_signal, proc { |p, s| format('Command will be stopped with `kill -%s %s`', s, p) }
+        output_format :timeout, '# %s-timeout: %s seconds'
+        output_format :wait_time, '# %s: %s seconds'
+
+        # rubocop:disable Metrics/LineLength
+        if @options[:stdout]
+          warn('The use of "@announce_stdout-instance" variable and "options[:stdout] = true" for Announcer.new is deprecated. Please use "announcer.activate(:stdout)" instead.')
+          activate :stdout
+        end
+        if @options[:stderr]
+          warn('The use of "@announce_stderr-instance" variable and "options[:stderr] = true" for Announcer.new is deprecated. Please use "announcer.activate(:stderr)" instead.')
+          activate :stderr
+        end
+        if @options[:dir]
+          warn('The use of "@announce_dir-instance" variable and "options[:dir] = true" for Announcer.new is deprecated. Please use "announcer.activate(:directory)" instead.')
+          activate :directory
+        end
+        if @options[:cmd]
+          warn('The use of "@announce_cmd-instance" variable and "options[:cmd] = true" for Announcer.new is deprecated. Please use "announcer.activate(:command)" instead.')
+          activate :command
+        end
+        if @options[:env]
+          warn('The use of "@announce_env-instance" variable and "options[:env] = true" for Announcer.new is deprecated. Please use "announcer.activate(:modified_environment)" instead.')
+          activate :modified_enviroment
+        end
+        # rubocop:enable Metrics/LineLength
+      end
+      # rubocop:enable Metrics/MethodLength
+
+      def output_format(channel, string = '%s', &block)
+        if block_given?
+          output_formats[channel.to_sym] = block
+        elsif  string.is_a?(Proc)
+          output_formats[channel.to_sym] = string
+        else
+          output_formats[channel.to_sym] = proc { |*args| format(string, *args) }
+        end
+      end
+
+      public
+
+      # Reset announcer
+      def reset
+        @default_announcer = @announcers.last
+        @announcer         = @announcers.first
+      end
+
+      # Change mode of announcer
+      #
+      # @param [Symbol] m
+      #   The mode to set
+      def mode=(m)
+        @announcer = @announcers.find { |a| f.mode? m.to_sym }
+
+        self
+      end
+
+      # Check if channel is activated
+      #
+      # @param [Symbol] channel
+      #   The name of the channel to check
+      def activated?(channel)
+        channels[channel.to_sym] == true
+      end
+
+      # Activate a channel
+      #
+      # @param [Symbol] channel
+      #   The name of the channel to activate
+      def activate(channel)
+        channels[channel.to_sym] = true
+
+        self
+      end
+
+      # Announce information to channel
+      #
+      # @param [Symbol] channel
+      #   The name of the channel to check
+      #
+      # @param [Array] args
+      #   Arguments
+      def announce(channel, *args)
+        channel = channel.to_sym
+
+        the_output_format = if output_formats.key? channel
+                              output_formats[channel]
+                            else
+                              proc { |v| format('%s', v) }
+                            end
+
+        message = the_output_format.call(*args)
+
+        announcer.announce(message) if channels[channel]
+
+        default_announcer.announce message
+      end
+
+      # @deprecated
+      def stdout(content)
+        warn('The announcer now has a new api to activate channels. Please use this one: announce(:stdout, message)')
+        announce :stdout, content
+      end
+
+      # @deprecated
+      def stderr(content)
+        warn('The announcer now has a new api to activate channels. Please use this one: announce(:stderr, message)')
+        announce :stderr, content
+      end
+
+      # @deprecated
+      def dir(dir)
+        warn('The announcer now has a new api to activate channels. Please use this one announce(:directory, message)')
+        announce :directory, dir
+      end
+
+      # @deprecated
+      def cmd(cmd)
+        warn('The announcer now has a new api to activate channels. Please use this one announce(:command, message)')
+        announce :command, cmd
+      end
+
+      # @deprecated
+      def env(name, value)
+        warn('The announcer now has a new api to activate channels. Please use this one: announce(:changed_environment, key, value)')
+
+        announce :changed_environment, name, value
+      end
+    end
+  end
+end
diff --git a/lib/aruba/aruba_logger.rb b/lib/aruba/platforms/aruba_logger.rb
similarity index 100%
rename from lib/aruba/aruba_logger.rb
rename to lib/aruba/platforms/aruba_logger.rb
diff --git a/lib/aruba/platforms/command_monitor.rb b/lib/aruba/platforms/command_monitor.rb
new file mode 100644
index 0000000..5b102c3
--- /dev/null
+++ b/lib/aruba/platforms/command_monitor.rb
@@ -0,0 +1,244 @@
+require 'aruba/errors'
+
+module Aruba
+  # The command monitor is part of the private API of Aruba.
+  class CommandMonitor
+    private
+
+    attr_reader :event_bus, :announcer
+
+    public
+
+    attr_reader :registered_commands, :last_command_started
+
+    class DefaultLastCommandStopped
+      def nil?
+        true
+      end
+
+      def method_missing(*)
+        fail NoCommandHasBeenStartedError, 'No last command stopped available'
+      end
+    end
+
+    class DefaultLastCommandStarted
+      def nil?
+        true
+      end
+
+      def method_missing(*)
+        fail NoCommandHasBeenStoppedError, 'No last command started available'
+      end
+    end
+
+    # rubocop:disable Metrics/MethodLength
+    def initialize(opts = {})
+      @registered_commands = []
+      @event_bus = opts.fetch(:event_bus)
+      @announcer = opts.fetch(:announcer)
+
+      @last_command_stopped = DefaultLastCommandStopped.new
+      @last_command_started = DefaultLastCommandStarted.new
+    rescue KeyError => e
+      raise ArgumentError, e.message
+    end
+
+    if Aruba::VERSION < '1'
+      # Return the last command stopped
+      def last_command_stopped
+        return @last_command_stopped unless @last_command_stopped.nil?
+
+        registered_commands.each(&:stop)
+
+        @last_command_stopped
+      end
+    else
+      attr_reader :last_command_stopped
+    end
+
+    # Start given command
+    #
+    # @param [String] cmd
+    #   The commandline of the command
+    # @param [Numeric] timeout
+    #   The time to wait for the command to stop
+    def start_command(cmd, opts = {})
+      opts[:event_bus] = event_bus
+      command = Command.new(cmd, opts)
+      register_command(command)
+
+      command.start
+
+      self
+    end
+
+    # Set last command started
+    #
+    # @param [String] cmd
+    #   The commandline of the command
+    def last_command_started=(cmd)
+      @last_command_started = find(cmd)
+    end
+
+    # Set last command started
+    #
+    # @param [String] cmd
+    #   The commandline of the command
+    def last_command_stopped=(cmd)
+      @last_command_stopped = find(cmd)
+    end
+
+    # Find command
+    #
+    # @yield [Command]
+    #   This yields the found command
+    def find(cmd)
+      cmd = cmd.commandline if cmd.respond_to? :commandline
+      command = registered_commands.find { |c| c.commandline == cmd }
+
+      fail ArgumentError, "No command named '#{cmd}' has been started" if command.nil?
+
+      command
+    end
+
+    # Clear list of known commands
+    def clear
+      registered_commands.each(&:terminate)
+      registered_commands.clear
+
+      self
+    end
+
+    # @deprecated
+    # Fetch output (stdout, stderr) from command
+    #
+    # @param [String] cmd
+    #   The command
+    def output_from(cmd)
+      cmd = Utils.detect_ruby(cmd)
+      find(cmd).output
+    end
+
+    # @deprecated
+    # Fetch stdout from command
+    #
+    # @param [String] cmd
+    #   The command
+    def stdout_from(cmd)
+      cmd = Utils.detect_ruby(cmd)
+      find(cmd).stdout
+    end
+
+    # @deprecated
+    # Fetch stderr from command
+    #
+    # @param [String] cmd
+    #   The command
+    def stderr_from(cmd)
+      cmd = Utils.detect_ruby(cmd)
+      find(cmd).stderr
+    end
+
+    # @deprecated
+    # Get stdout of all commands
+    #
+    # @return [String]
+    #   The stdout of all command which have run before
+    def all_stdout
+      registered_commands.each(&:stop)
+
+      if RUBY_VERSION < '1.9.3'
+        # rubocop:disable Style/EachWithObject
+        registered_commands.inject("") { |a, e| a << e.stdout; a }
+        # rubocop:enable Style/EachWithObject
+      else
+        registered_commands.each_with_object("") { |e, a| a << e.stdout }
+      end
+    end
+
+    # @deprecated
+    # Get stderr of all commands
+    #
+    # @return [String]
+    #   The stderr of all command which have run before
+    def all_stderr
+      registered_commands.each(&:stop)
+
+      if RUBY_VERSION < '1.9.3'
+        # rubocop:disable Style/EachWithObject
+        registered_commands.inject("") { |a, e| a << e.stderr; a }
+        # rubocop:enable Style/EachWithObject
+      else
+        registered_commands.each_with_object("") { |e, a| a << e.stderr }
+      end
+    end
+
+    # @deprecated
+    # Get stderr and stdout of all commands
+    #
+    # @return [String]
+    #   The stderr and stdout of all command which have run before
+    def all_output
+      all_stdout << all_stderr
+    end
+
+    # @deprecated
+    def last_exit_status
+      Aruba.platform.deprecated('The use of "#last_exit_status" is deprecated. Use "last_command_(started|stopped).exit_status" instead')
+
+      return @last_exit_status if @last_exit_status
+      registered_commands.each(&:stop)
+      @last_exit_status
+    end
+
+    # @deprecated
+    def stop_process(process)
+      @last_command_stopped = process
+      @last_exit_status     = process.stop(announcer)
+    end
+
+    # @deprecated
+    def terminate_process!(process)
+      process.terminate
+    end
+
+    # @deprecated
+    def stop_processes!
+      Aruba.platform.deprecated('The use of "#stop_processes!" is deprecated.')
+
+      registered_commands.each(&:stop)
+    end
+
+    # @deprecated
+    # Terminate all running processes
+    def terminate_processes
+      Aruba.platform.deprecated('The use of "#terminate_processes" is deprecated.')
+
+      registered_commands.each(&:terminate)
+    end
+
+    # @deprecated
+    def only_processes
+      Aruba.platform.deprecated('The use of "#only_processes" is deprecated.')
+
+      registered_commands
+    end
+
+    # @deprecated
+    def get_process(wanted)
+      command = find(wanted)
+      raise ArgumentError.new("No process named '#{wanted}' has been started") unless command
+
+      command
+    end
+
+    private
+
+    # Register
+    def register_command(cmd)
+      registered_commands << cmd
+
+      self
+    end
+  end
+end
diff --git a/lib/aruba/platforms/unix_platform.rb b/lib/aruba/platforms/unix_platform.rb
index 2aecd46..6f5d88a 100644
--- a/lib/aruba/platforms/unix_platform.rb
+++ b/lib/aruba/platforms/unix_platform.rb
@@ -11,6 +11,9 @@ require 'aruba/platforms/determine_disk_usage'
 require 'aruba/platforms/aruba_file_creator'
 require 'aruba/platforms/aruba_fixed_size_file_creator'
 require 'aruba/platforms/local_environment'
+require 'aruba/platforms/aruba_logger'
+require 'aruba/platforms/announcer'
+require 'aruba/platforms/command_monitor'
 
 module Aruba
   # This abstracts OS-specific things
@@ -35,6 +38,18 @@ module Aruba
         UnixCommandString
       end
 
+      def announcer
+        Announcer
+      end
+
+      def command_monitor
+        CommandMonitor
+      end
+
+      def logger
+        ArubaLogger
+      end
+
       def determine_file_size(*args)
         DetermineFileSize.new.call(*args)
       end
@@ -151,8 +166,8 @@ module Aruba
       end
 
       # Path is executable
-      def executable_file?(f)
-        File.file?(f) && File.executable?(f)
+      def executable?(f)
+        File.executable?(f)
       end
 
       # Expand path
diff --git a/lib/aruba/platforms/unix_which.rb b/lib/aruba/platforms/unix_which.rb
index 7915f20..eff34fd 100644
--- a/lib/aruba/platforms/unix_which.rb
+++ b/lib/aruba/platforms/unix_which.rb
@@ -22,7 +22,7 @@ module Aruba
         end
 
         def call(program, path)
-          return File.expand_path(program) if Aruba.platform.executable_file?(program)
+          return File.expand_path(program) if Aruba.platform.executable?(program)
 
           nil
         end
@@ -43,7 +43,7 @@ module Aruba
             next unless Aruba.platform.exist?(dir) # In case of bogus second argument
 
             found = Dir[File.join(dir, program)].first
-            return found if found && Aruba.platform.executable_file?(found)
+            return found if found && Aruba.platform.executable?(found)
           end
 
           nil
diff --git a/lib/aruba/platforms/windows_which.rb b/lib/aruba/platforms/windows_which.rb
index 6d56dd4..272c1ba 100644
--- a/lib/aruba/platforms/windows_which.rb
+++ b/lib/aruba/platforms/windows_which.rb
@@ -25,7 +25,7 @@ module Aruba
           # Expand `#path_exts`
           found = Dir[program].first
 
-          return File.expand_path(found) if found && Aruba.platform.executable_file?(found)
+          return File.expand_path(found) if found && Aruba.platform.executable?(found)
           nil
         end
       end
@@ -53,7 +53,7 @@ module Aruba
             found = Dir[file].first
 
             # Convert all forward slashes to backslashes if supported
-            if found && Aruba.platform.executable_file?(found)
+            if found && Aruba.platform.executable?(found)
               found.tr!(File::SEPARATOR, File::ALT_SEPARATOR)
               return found
             end
diff --git a/lib/aruba/process_monitor.rb b/lib/aruba/process_monitor.rb
deleted file mode 100644
index 9a2c3da..0000000
--- a/lib/aruba/process_monitor.rb
+++ /dev/null
@@ -1,201 +0,0 @@
-require 'aruba/processes/null_process'
-
-module Aruba
-  class ProcessMonitor
-    private
-
-    attr_reader :processes, :announcer
-
-    public
-
-    def initialize(announcer)
-      @processes = []
-      @announcer = announcer
-    end
-
-    def last_exit_status
-      Aruba.platform.deprecated('The use of "#last_exit_status" is deprecated. Use "last_command_(started|stopped).exit_status" instead')
-
-      return @last_exit_status if @last_exit_status
-      all_commands.each { |c| stop_process(c) }
-      @last_exit_status
-    end
-
-    def last_command_stopped
-      return @last_command_stopped if @last_command_stopped
-      return Command.new('false',
-                         :mode              => :null,
-                         :exit_timeout      => 0,
-                         :io_wait_timeout   => 0,
-                         :working_directory => '/tmp',
-                         :environment       => {},
-                         :main_class        => nil,
-                         :stop_signal       => nil,
-                         :startup_wait_time => nil
-                        ) if all_commands.empty?
-
-      all_commands.each { |c| stop_process(c) }
-
-      @last_command_stopped
-    end
-
-    def last_command_started
-      return Command.new('false',
-                         :mode              => :null,
-                         :exit_timeout      => 0,
-                         :io_wait_timeout   => 0,
-                         :working_directory => '/tmp',
-                         :environment       => {},
-                         :main_class        => nil,
-                         :stop_signal       => nil,
-                         :startup_wait_time => nil
-                        ) unless processes.last.is_a? Array
-
-      processes.last[1]
-    end
-
-    def stop_process(process)
-      @last_command_stopped = process
-      @last_exit_status     = process.stop(announcer)
-    end
-
-    def terminate_process!(process)
-      @last_command_stopped = process
-      @last_exit_status     = process.terminate
-    end
-
-    def stop_processes!
-      Aruba.platform.deprecated('The use of "#stop_processes!" is deprecated. Use "#stop_all_commands" instead')
-
-      stop_all_commands
-    end
-
-    def stop_all_commands
-      all_commands.each { |c| c.stop(announcer) }
-    end
-
-    # Terminate all running processes
-    def terminate_processes
-      Aruba.platform.deprecated('The use of "#terminate_processes" is deprecated. Use "#all_commands.each(&:terminate)" instead')
-
-      processes.each do |_, process|
-        terminate_process(process)
-        stop_process(process)
-      end
-    end
-
-    def register_process(name, process)
-      processes << [name, process]
-
-      [name, process]
-    end
-
-    def get_process(wanted)
-      matching_processes = processes.reverse.find{ |name, _| name == wanted }
-      raise ArgumentError.new("No process named '#{wanted}' has been started") unless matching_processes
-      matching_processes.last
-    end
-
-    def only_processes
-      Aruba.platform.deprecated('The use of "#only_processes" is deprecated. Use "#all_commands" instead')
-
-      processes.collect{ |_, process| process }
-    end
-
-    # Fetch output (stdout, stderr) from command
-    #
-    # @param [String] cmd
-    #   The command
-    def output_from(cmd)
-      cmd = Aruba.platform.detect_ruby(cmd)
-      get_process(cmd).output
-    end
-
-    # Fetch stdout from command
-    #
-    # @param [String] cmd
-    #   The command
-    def stdout_from(cmd)
-      cmd = Aruba.platform.detect_ruby(cmd)
-      get_process(cmd).stdout
-    end
-
-    # Fetch stderr from command
-    #
-    # @param [String] cmd
-    #   The command
-    def stderr_from(cmd)
-      cmd = Aruba.platform.detect_ruby(cmd)
-      get_process(cmd).stderr
-    end
-
-    # Get stdout of all processes
-    #
-    # @return [String]
-    #   The stdout of all process which have run before
-    def all_stdout
-      # rubocop:disable Metrics/LineLength
-      Aruba.platform.deprecated('The use of "#all_stdout" is deprecated. Use `all_commands.map { |c| c.stdout }.join("\n") instead. If you need to check for some output use "expect(all_commands).to have_output_on_stdout /output/" instead')
-      # rubocop:enable Metrics/LineLength
-
-      stop_all_commands
-
-      if RUBY_VERSION < '1.9'
-        out = ''
-        only_processes.each { |ps| out << ps.stdout }
-
-        out
-      else
-        only_processes.each_with_object("") { |ps, o| o << ps.stdout }
-      end
-    end
-
-    # Get stderr of all processes
-    #
-    # @return [String]
-    #   The stderr of all process which have run before
-    def all_stderr
-      # rubocop:disable Metrics/LineLength
-      Aruba.platform.deprecated('The use of "#all_stderr" is deprecated. Use `all_commands.map { |c| c.stderr }.join("\n") instead. If you need to check for some output use "expect(all_commands).to have_output_on_stderr /output/" instead')
-      # rubocop:enable Metrics/LineLength
-
-      stop_all_commands
-
-      if RUBY_VERSION < '1.9'
-        out = ''
-        only_processes.each { |ps| out << ps.stderr }
-
-        out
-      else
-        only_processes.each_with_object("") { |ps, o| o << ps.stderr }
-      end
-    end
-
-    # Get stderr and stdout of all processes
-    #
-    # @return [String]
-    #   The stderr and stdout of all process which have run before
-    def all_output
-      # rubocop:disable Metrics/LineLength
-      Aruba.platform.deprecated('The use of "#all_output" is deprecated. Use `all_commands.map { |c| c.output }.join("\n") instead. If you need to check for some output use "expect(all_commands).to have_output /output/" instead')
-      # rubocop:enable Metrics/LineLength
-
-      all_stdout << all_stderr
-    end
-
-    # Return all commands
-    #
-    # @return [Array]
-    #   A list of all commands
-    def all_commands
-      processes.collect { |_, process| process }
-    end
-
-    # Clear list of processes
-    def clear
-      processes.clear
-
-      self
-    end
-  end
-end
diff --git a/lib/aruba/processes/basic_process.rb b/lib/aruba/processes/basic_process.rb
index dc29dbd..dfd28a9 100644
--- a/lib/aruba/processes/basic_process.rb
+++ b/lib/aruba/processes/basic_process.rb
@@ -9,9 +9,9 @@ module Aruba
     #
     # @private
     class BasicProcess
-      attr_reader :exit_status, :environment, :startup_wait_time
+      attr_reader :exit_status, :environment, :working_directory, :main_class, :io_wait_timeout, :exit_timeout, :startup_wait_time
 
-      def initialize(cmd, exit_timeout, io_wait, working_directory, environment = ENV.to_hash.dup, main_class = nil, stop_signal = nil, startup_wait_time = 0)
+      def initialize(cmd, exit_timeout, io_wait_timeout, working_directory, environment = ENV.to_hash.dup, main_class = nil, stop_signal = nil, startup_wait_time = 0)
         @cmd               = cmd
         @working_directory = working_directory
         @environment       = environment
@@ -20,8 +20,8 @@ module Aruba
         @stop_signal       = stop_signal
         @startup_wait_time = startup_wait_time
 
-        @exit_timeout = exit_timeout
-        @io_wait      = io_wait
+        @exit_timeout    = exit_timeout
+        @io_wait_timeout = io_wait_timeout
       end
 
       # Return command line
diff --git a/lib/aruba/processes/in_process.rb b/lib/aruba/processes/in_process.rb
index 283d15b..d8c1104 100644
--- a/lib/aruba/processes/in_process.rb
+++ b/lib/aruba/processes/in_process.rb
@@ -40,7 +40,7 @@ module Aruba
       # @private
       attr_reader :main_class
 
-      def initialize(cmd, exit_timeout, io_wait, working_directory, environment = ENV.to_hash.dup, main_class = nil, stop_signal = nil, startup_wait_time = 0)
+      def initialize(cmd, exit_timeout, io_wait_timeout, working_directory, environment = ENV.to_hash.dup, main_class = nil, stop_signal = nil, startup_wait_time = 0)
         @cmd               = cmd
         @argv              = arguments
         @stdin             = StringIO.new
diff --git a/lib/aruba/processes/null_process.rb b/lib/aruba/processes/null_process.rb
deleted file mode 100644
index 7904f3f..0000000
--- a/lib/aruba/processes/null_process.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'aruba/processes/basic_process'
-
-module Aruba
-  module Processes
-    # Null Process
-    #
-    # `NullProcess` is not meant for direct use - `BasicProcess.new` - by users.
-    #
-    # @private
-    class NullProcess < BasicProcess
-      def self.match?(mode)
-        mode == :null
-      end
-
-      # Pid
-      def pid
-        0
-      end
-
-      # String representation
-      def to_s
-        ''
-      end
-    end
-  end
-end
diff --git a/lib/aruba/processes/spawn_process.rb b/lib/aruba/processes/spawn_process.rb
index a8da8bd..b3e86f5 100644
--- a/lib/aruba/processes/spawn_process.rb
+++ b/lib/aruba/processes/spawn_process.rb
@@ -29,12 +29,12 @@ module Aruba
       # @params [Integer] exit_timeout
       #   The timeout until we expect the command to be finished
       #
-      # @params [Integer] io_wait
+      # @params [Integer] io_wait_timeout
       #   The timeout until we expect the io to be finished
       #
       # @params [String] working_directory
       #   The directory where the command will be executed
-      def initialize(cmd, exit_timeout, io_wait, working_directory, environment = ENV.to_hash.dup, main_class = nil, stop_signal = nil, startup_wait_time = 0)
+      def initialize(cmd, exit_timeout, io_wait_timeout, working_directory, environment = ENV.to_hash.dup, main_class = nil, stop_signal = nil, startup_wait_time = 0)
         super
 
         @process      = nil
@@ -168,7 +168,7 @@ module Aruba
       end
 
       # rubocop:disable Metrics/MethodLength
-      def stop(reader)
+      def stop(*)
         return @exit_status if stopped?
 
         begin
@@ -178,13 +178,6 @@ module Aruba
         end
 
         terminate
-
-        if reader
-          reader.announce :stdout, @stdout_cache
-          reader.announce :stderr, @stderr_cache
-        end
-
-        @exit_status
       end
       # rubocop:enable Metrics/MethodLength
 
diff --git a/lib/aruba/rspec.rb b/lib/aruba/rspec.rb
index 724d5b6..ca5ca90 100644
--- a/lib/aruba/rspec.rb
+++ b/lib/aruba/rspec.rb
@@ -42,37 +42,45 @@ RSpec.configure do |config|
     next unless self.class.include?(Aruba::Api)
 
     if example.metadata[:announce_environment]
-      Aruba.platform.deprecated 'announce_environment is deprecated. Use announce_modified_environment instead'
+      Aruba.platform.deprecated 'announce_environment is deprecated. Use announce_changed_environment instead'
 
-      announcer.activate(:modified_environment)
+      aruba.announcer.activate(:changed_environment)
     end
 
-    announcer.activate(:full_environment)     if example.metadata[:announce_full_environment]
-    announcer.activate(:modified_environment) if example.metadata[:announce_modified_environment]
-    announcer.activate(:command)              if example.metadata[:announce_command]
-    announcer.activate(:directory)            if example.metadata[:announce_directory]
-    announcer.activate(:stdout)               if example.metadata[:announce_stdout]
-    announcer.activate(:stderr)               if example.metadata[:announce_stderr]
-    announcer.activate(:timeout)              if example.metadata[:announce_timeout]
-    announcer.activate(:wait_time)            if example.metadata[:announce_wait_time]
-    announcer.activate(:stop_signal)          if example.metadata[:announce_stop_signal]
+    aruba.announcer.activate(:full_environment)     if example.metadata[:announce_full_environment]
+    aruba.announcer.activate(:changed_environment)  if example.metadata[:announce_changed_environment]
+
+    if example.metadata[:announce_modified_environment]
+      Aruba.platform.deprecated 'announce_modified_environment is deprecated. Use announce_changed_environment instead'
+
+      aruba.announcer.activate(:changed_environment)
+    end
+
+    aruba.announcer.activate(:command)              if example.metadata[:announce_command]
+    aruba.announcer.activate(:directory)            if example.metadata[:announce_directory]
+    aruba.announcer.activate(:full_environment)     if example.metadata[:announce_full_environment]
+    aruba.announcer.activate(:stderr)               if example.metadata[:announce_stderr]
+    aruba.announcer.activate(:stdout)               if example.metadata[:announce_stdout]
+    aruba.announcer.activate(:stop_signal)          if example.metadata[:announce_stop_signal]
+    aruba.announcer.activate(:timeout)              if example.metadata[:announce_timeout]
+    aruba.announcer.activate(:wait_time)            if example.metadata[:announce_wait_time]
 
     if example.metadata[:announce_output]
-      announcer.activate(:stderr)
-      announcer.activate(:stdout)
+      aruba.announcer.activate(:stderr)
+      aruba.announcer.activate(:stdout)
     end
 
     if example.metadata[:announce]
-      announcer.activate(:stderr)
-      announcer.activate(:stdout)
-      announcer.activate(:environment)
-      announcer.activate(:modified_environment)
-      announcer.activate(:full_environment)
-      announcer.activate(:command)
-      announcer.activate(:directory)
-      announcer.activate(:stop_signal)
-      announcer.activate(:timeout)
-      announcer.activate(:wait_time)
+      aruba.announcer.activate(:changed_environment)
+      aruba.announcer.activate(:command)
+      aruba.announcer.activate(:directory)
+      aruba.announcer.activate(:environment)
+      aruba.announcer.activate(:full_environment)
+      aruba.announcer.activate(:stderr)
+      aruba.announcer.activate(:stdout)
+      aruba.announcer.activate(:stop_signal)
+      aruba.announcer.activate(:timeout)
+      aruba.announcer.activate(:wait_time)
     end
   end
 
diff --git a/lib/aruba/runtime.rb b/lib/aruba/runtime.rb
index 4e7d737..2b3ae15 100644
--- a/lib/aruba/runtime.rb
+++ b/lib/aruba/runtime.rb
@@ -1,18 +1,47 @@
 require 'aruba/config'
-require 'aruba/aruba_logger'
+require 'aruba/aruba_path'
+require 'aruba/config_wrapper'
+require 'aruba/events'
+require 'event/bus'
 
 module Aruba
   class Runtime
-    attr_reader :config, :current_directory, :environment, :root_directory, :logger
+    attr_reader :current_directory, :root_directory
+    attr_accessor :config, :environment, :logger, :command_monitor, :announcer, :event_bus
 
-    def initialize
-      @config            = Aruba.config.make_copy
+    def initialize(opts = {})
+      @environment     = opts.fetch(:environment, Aruba.platform.environment_variables)
+      @event_bus     = ::Event::Bus.new(::Event::NameResolver.new(Aruba::Events))
+      @announcer       = opts.fetch(:announcer, Aruba.platform.announcer.new)
+
+      @config            = opts.fetch(:config, ConfigWrapper.new(Aruba.config.make_copy, @event_bus))
       @current_directory = ArubaPath.new(@config.working_directory)
       @root_directory    = ArubaPath.new(@config.root_directory)
-      @environment       = Aruba.platform.environment_variables
 
-      @logger      = ArubaLogger.new
+      if Aruba::VERSION < '1'
+        @command_monitor = opts.fetch(:command_monitor, Aruba.platform.command_monitor.new(event_bus: @event_bus, announcer: @announcer))
+      else
+        @command_monitor = opts.fetch(:command_monitor, Aruba.platform.command_monitor.new(event_bus: @event_bus))
+      end
+
+      @logger = opts.fetch(:logger, Aruba.platform.logger.new)
       @logger.mode = @config.log_level
+
+      @setup_done = false
+    end
+
+    # @private
+    #
+    # Setup of aruba is finshed. Should be used only internally.
+    def setup_done
+      @setup_done = true
+    end
+
+    # @private
+    #
+    # Has aruba already been setup. Should be used only internally.
+    def setup_already_done?
+      @setup_done == true
     end
 
     # The path to the directory which contains fixtures
diff --git a/lib/aruba/setup.rb b/lib/aruba/setup.rb
new file mode 100644
index 0000000..18ea633
--- /dev/null
+++ b/lib/aruba/setup.rb
@@ -0,0 +1,86 @@
+module Aruba
+  class Setup
+    private
+
+    attr_reader :runtime
+
+    public
+
+    def initialize(runtime)
+      @runtime      = runtime
+    end
+
+    def call
+      return if runtime.setup_already_done?
+
+      working_directory
+      events
+
+      runtime.setup_done
+
+      self
+    end
+
+    private
+
+    def working_directory
+      Aruba.platform.rm File.join(runtime.config.root_directory, runtime.config.working_directory), :force => true
+      Aruba.platform.mkdir File.join(runtime.config.root_directory, runtime.config.working_directory)
+      Aruba.platform.chdir runtime.config.root_directory
+    end
+
+    # rubocop:disable Metrics/MethodLength
+    def events
+      runtime.event_bus.register(
+        :command_started,
+        ->(event) do
+          runtime.announcer.announce :command, event.entity.commandline
+          runtime.announcer.announce :timeout, 'exit', event.entity.exit_timeout
+          runtime.announcer.announce :timeout, 'io wait', event.entity.io_wait_timeout
+          runtime.announcer.announce :full_environment, event.entity.environment
+        end
+      )
+
+      runtime.event_bus.register(
+        :command_started,
+        ->(event) do
+          runtime.command_monitor.last_command_started = event.entity
+        end
+      )
+
+      runtime.event_bus.register(
+        :command_stopped,
+        ->(event) do
+          runtime.announcer.announce :stdout, event.entity.stdout
+          runtime.announcer.announce :stderr, event.entity.stderr
+        end
+      )
+
+      runtime.event_bus.register(
+        :command_stopped,
+        ->(event) do
+          runtime.command_monitor.last_command_stopped = event.entity
+        end
+      )
+
+      runtime.event_bus.register(
+        [:changed_environment_variable, :added_environment_variable, :deleted_environment_variable],
+        ->(event) do
+          runtime.announcer.announce :changed_environment, event.entity[:changed][:name], event.entity[:changed][:value]
+          runtime.announcer.announce :environment, event.entity[:changed][:name], event.entity[:changed][:value]
+        end
+      )
+
+      runtime.event_bus.register(
+        :changed_working_directory,
+        ->(event) { runtime.announcer.announce :directory, event.entity[:new] }
+      )
+
+      runtime.event_bus.register(
+        :changed_configuration,
+        ->(event) { runtime.announcer.announce :configuration, event.entity[:changed][:name], event.entity[:changed][:value] }
+      )
+    end
+    # rubocop:enable Metrics/MethodLength
+  end
+end
diff --git a/spec/aruba/api_spec.rb b/spec/aruba/api_spec.rb
index 97f9e3f..de4753f 100644
--- a/spec/aruba/api_spec.rb
+++ b/spec/aruba/api_spec.rb
@@ -6,26 +6,6 @@ require 'fileutils'
 describe Aruba::Api  do
   include_context 'uses aruba API'
 
-  describe 'current_directory' do
-    it "should return the current dir as 'tmp/aruba'" do
-      expect(@aruba.aruba.current_directory.to_s).to match(/^tmp\/aruba$/)
-    end
-
-    it "can be cleared" do
-      write_file('test', 'test test test')
-
-      cd('.') do
-        expect(File.exist?('test')).to be true
-      end
-
-      setup_aruba
-
-      cd('.') do
-        expect(File.exist?('test')).to be false
-      end
-    end
-  end
-
   describe '#all_paths' do
     let(:name) { @file_name }
     let(:path) { @file_path }
@@ -1096,19 +1076,17 @@ describe Aruba::Api  do
 
   describe 'tags' do
     describe '@announce_stdout' do
-      after(:each) { @aruba.all_commands.each { |c| c.stop(@aruba.announcer) } }
+      after(:each) { @aruba.all_commands.each(&:stop) }
 
       context 'enabled' do
         before :each do
-          @aruba.announcer.activate(:stdout)
+          @aruba.aruba.announcer = instance_double 'Aruba::Platforms::Announcer'
+          expect(@aruba.aruba.announcer).to receive(:announce).with(:stdout, "hello world\n")
+          allow(@aruba.aruba.announcer).to receive(:announce)
         end
 
         it "should announce to stdout exactly once" do
-          result = capture(:stdout) do
-            @aruba.run_simple('echo "hello world"', false)
-          end
-
-          expect(result).to include('hello world')
+          @aruba.run_simple('echo "hello world"', false)
           expect(@aruba.all_output).to include('hello world')
         end
       end
@@ -1128,7 +1106,7 @@ describe Aruba::Api  do
 
   describe "#assert_not_matching_output" do
     before(:each){ @aruba.run_simple("echo foo", false) }
-    after(:each) { @aruba.all_commands.each { |c| c.stop(@aruba.announcer) } }
+    after(:each) { @aruba.all_commands.each(&:stop) }
 
     it "passes when the output doesn't match a regexp" do
       @aruba.assert_not_matching_output "bar", @aruba.all_output
@@ -1141,8 +1119,9 @@ describe Aruba::Api  do
   end
 
   describe '#run' do
-    before(:each){@aruba.run "cat"}
-    after(:each) { @aruba.all_commands.each { |c| c.stop(@aruba.announcer) } }
+    before(:each){ @aruba.run 'cat' }
+    after(:each) { @aruba.all_commands.each(&:stop) }
+
     it "respond to input" do
       @aruba.type "Hello"
       @aruba.type ""
@@ -1165,16 +1144,14 @@ describe Aruba::Api  do
 
   describe "#run_simple" do
     before(:each){@aruba.run_simple "true"}
-    after(:each) { @aruba.all_commands.each { |c| c.stop(@aruba.announcer) } }
+    after(:each) { @aruba.all_commands.each(&:stop) }
     describe "get_process" do
       it "returns a process" do
         expect(@aruba.get_process("true")).not_to be(nil)
       end
 
       it "raises a descriptive exception" do
-        expect do
-          expect(@aruba.get_process("false")).not_to be(nil)
-        end.to raise_error(ArgumentError, "No process named 'false' has been started")
+        expect { @aruba.get_process("false") }.to raise_error ArgumentError, "No command named 'false' has been started"
       end
     end
   end
@@ -1195,7 +1172,7 @@ describe Aruba::Api  do
 
   describe "#set_environment_variable" do
     after(:each) do
-      @aruba.all_commands.each { |c| c.stop(@aruba.announcer) }
+      @aruba.all_commands.each(&:stop)
       @aruba.restore_env
     end
 
@@ -1214,7 +1191,7 @@ describe Aruba::Api  do
   end
 
   describe "#restore_env" do
-    after(:each) { @aruba.all_commands.each { |c| c.stop(@aruba.announcer) } }
+    after(:each) { @aruba.all_commands.each(&:stop) }
     it "restores environment variable" do
       @aruba.set_env 'LONG_LONG_ENV_VARIABLE', 'true'
       @aruba.restore_env
diff --git a/spec/aruba/config_wrapper_spec.rb b/spec/aruba/in_config_wrapper_spec.rb
similarity index 93%
rename from spec/aruba/config_wrapper_spec.rb
rename to spec/aruba/in_config_wrapper_spec.rb
index 2e1c657..379d052 100644
--- a/spec/aruba/config_wrapper_spec.rb
+++ b/spec/aruba/in_config_wrapper_spec.rb
@@ -1,6 +1,6 @@
 require 'spec_helper'
 
-RSpec.describe Aruba::ConfigWrapper do
+RSpec.describe Aruba::InConfigWrapper do
   subject(:wrapper) { described_class.new(config) }
 
   let(:config) { {} }
diff --git a/spec/aruba/spawn_process_spec.rb b/spec/aruba/spawn_process_spec.rb
index 2a1c9e0..fe32a57 100644
--- a/spec/aruba/spawn_process_spec.rb
+++ b/spec/aruba/spawn_process_spec.rb
@@ -11,7 +11,8 @@ RSpec.describe Aruba::Processes::SpawnProcess do
   let(:main_class) { nil }
 
   describe "#stdout" do
-    before(:each) { process.run! }
+    before(:each) { process.start }
+    before(:each) { process.stop }
 
     context 'when invoked once' do
       it { expect(process.stdout).to eq "yo\n" }
@@ -25,7 +26,8 @@ RSpec.describe Aruba::Processes::SpawnProcess do
   describe "#stderr" do
     let(:command) { 'fixtures/spawn_process/stderr.sh yo' }
 
-    before(:each) { process.run! }
+    before(:each) { process.start }
+    before(:each) { process.stop }
 
     context 'when invoked once' do
       it { expect(process.stderr).to eq "yo\n" }
@@ -37,29 +39,22 @@ RSpec.describe Aruba::Processes::SpawnProcess do
   end
 
   describe "#stop" do
-    let(:reader) { instance_double('Aruba::Announcer') }
-
-    before(:each) { process.run! }
-
-    before :each do
-      expect(reader).to receive(:announce).with(:stdout, "yo\n")
-      allow(reader).to receive(:announce)
-    end
+    before(:each) { process.start }
 
     context 'when stopped successfully' do
-      it { process.stop(reader) }
+      it { process.stop }
     end
   end
 
-  describe "#run!" do
+  describe "#start" do
     context "when process run succeeds" do
-      it { expect { process.run! }.not_to raise_error }
+      it { expect { process.start }.not_to raise_error }
     end
 
     context "when process run fails" do
       let(:command) { 'does_not_exists' }
 
-      it { expect {process.run!}.to raise_error Aruba::LaunchError }
+      it { expect {process.start}.to raise_error Aruba::LaunchError }
     end
   end
 end
diff --git a/spec/support/configs/pry.rb b/spec/support/configs/pry.rb
new file mode 100644
index 0000000..ea3b78b
--- /dev/null
+++ b/spec/support/configs/pry.rb
@@ -0,0 +1,3 @@
+# Otherwise pry doesn't find it's RC file
+# if ENV['HOME'] is mocked
+ENV['PRYRC'] = File.expand_path('~/.pryrc')
diff --git a/spec/support/shared_contexts/aruba.rb b/spec/support/shared_contexts/aruba.rb
index f3a8842..a1aab3d 100644
--- a/spec/support/shared_contexts/aruba.rb
+++ b/spec/support/shared_contexts/aruba.rb
@@ -29,6 +29,7 @@ RSpec.shared_context 'uses aruba API' do
     @file_name = "test.txt"
     @file_size = 256
     @file_path = @aruba.expand_path(@file_name)
+    @aruba.setup_aruba
 
     raise "We must work with relative paths, everything else is dangerous" if ?/ == @aruba.aruba.current_directory[0]
   end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-aruba.git



More information about the Pkg-ruby-extras-commits mailing list