diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index e7e56e894..8e89e105d 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,6 +1,6 @@
 # This configuration was generated by
 # `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp`
-# using RuboCop version 1.56.4.
+# using RuboCop version 1.62.1.
 # The point is for the user to remove these configuration records
 # one by one as the offenses are removed from the code base.
 # Note that changes in the inspected code, or installation of new
@@ -154,3 +154,10 @@ Style/OptionalBooleanParameter:
     - 'lib/aruba/api/core.rb'
     - 'lib/aruba/platforms/aruba_file_creator.rb'
     - 'lib/aruba/setup.rb'
+
+# This cop supports safe autocorrection (--autocorrect).
+Style/RedundantLineContinuation:
+  Exclude:
+    - 'lib/aruba/cucumber/command.rb'
+    - 'lib/aruba/cucumber/file.rb'
+    - 'lib/aruba/cucumber/testing_frameworks.rb'
diff --git a/aruba.gemspec b/aruba.gemspec
index 4dc82aea9..12faf7853 100644
--- a/aruba.gemspec
+++ b/aruba.gemspec
@@ -35,10 +35,10 @@ Gem::Specification.new do |spec|
   spec.add_development_dependency "rake", [">= 12.0", "< 14.0"]
   spec.add_development_dependency "rake-manifest", "~> 0.2.0"
   spec.add_development_dependency "rspec", "~> 3.11"
-  spec.add_development_dependency "rubocop", ["~> 1.28", "!= 1.29.0"]
-  spec.add_development_dependency "rubocop-packaging", "~> 0.5.0"
-  spec.add_development_dependency "rubocop-performance", "~> 1.13"
-  spec.add_development_dependency "rubocop-rspec", "~> 2.8"
+  spec.add_development_dependency "rubocop", "~> 1.62"
+  spec.add_development_dependency "rubocop-packaging", "~> 0.5.2"
+  spec.add_development_dependency "rubocop-performance", "~> 1.21"
+  spec.add_development_dependency "rubocop-rspec", "~> 2.28"
   spec.add_development_dependency "simplecov", ">= 0.18.0", "< 0.23.0"
 
   spec.required_ruby_version = ">= 3.0.0"
diff --git a/spec/aruba/api/filesystem_spec.rb b/spec/aruba/api/filesystem_spec.rb
index a66992c73..88cc626db 100644
--- a/spec/aruba/api/filesystem_spec.rb
+++ b/spec/aruba/api/filesystem_spec.rb
@@ -117,71 +117,78 @@
   end
 
   describe "#touch" do
-    let(:options) { {} }
-
-    before do
-      @aruba.set_environment_variable "HOME", File.expand_path(@aruba.aruba.current_directory)
-    end
-
     context "when touching a file that does not exist" do
-      before do
-        @aruba.touch(name, options)
+      it "creates an empty file in an existing directory" do
+        @aruba.touch(name)
+
+        aggregate_failures do
+          expect(File.size(path)).to eq 0
+          expect(File.file?(path)).to be true
+        end
       end
 
-      context "and should be created in an existing directory" do
-        it { expect(File.size(path)).to eq 0 }
+      it "creates an empty file in a non-existing directory" do
+        name = "directory/test"
+        path = File.join(@aruba.aruba.current_directory, name)
 
-        it_behaves_like "an existing file"
+        @aruba.touch(name)
+        expect(File.file?(path)).to be true
       end
 
-      context "and should be created in a non-existing directory" do
-        let(:name) { "directory/test" }
-        let(:path) { File.join(@aruba.aruba.current_directory, "directory/test") }
+      it "creates a file relative to home if name includes ~" do
+        string = random_string
+        name = File.join("~", string)
+        path = File.join(@aruba.aruba.config.home_directory, string)
 
-        it_behaves_like "an existing file"
+        @aruba.touch(name)
+        expect(File.file?(path)).to be true
       end
 
-      context "and path includes ~" do
-        let(:string) { random_string }
-        let(:name) { File.join("~", string) }
-        let(:path) { File.join(@aruba.aruba.current_directory, string) }
+      it "sets mtime when passed as an option" do
+        time = Time.parse("2014-01-01 10:00:00")
 
-        it_behaves_like "an existing file"
+        @aruba.touch(name, mtime: time)
+        aggregate_failures do
+          expect(File.file?(path)).to be true
+          expect(File.mtime(path)).to eq time
+        end
       end
 
-      context "and the mtime should be set statically" do
-        let(:time) { Time.parse("2014-01-01 10:00:00") }
-        let(:options) { { mtime: Time.parse("2014-01-01 10:00:00") } }
+      it "creates multiple files when multiple names are given" do
+        names = %w(file1 file2 file3)
 
-        it_behaves_like "an existing file"
-        it { expect(File.mtime(path)).to eq time }
-      end
+        @aruba.touch(names)
 
-      context "and multiple file names are given" do
-        let(:name) { %w(file1 file2 file3) }
-        let(:path) do
-          %w(file1 file2 file3).map { |p| File.join(@aruba.aruba.current_directory, p) }
+        paths = names.map { |name| File.join(@aruba.aruba.current_directory, name) }
+        aggregate_failures do
+          paths.each do |path|
+            expect(File.file?(path)).to be true
+          end
         end
-
-        it_behaves_like "an existing file"
       end
     end
 
     context "when touching an existing directory" do
       let(:name) { %w(directory1) }
-      let(:path) { Array(name).map { |p| File.join(@aruba.aruba.current_directory, p) } }
+      let(:path) { File.join(@aruba.aruba.current_directory, name) }
 
       before do
-        Array(path).each { |p| Aruba.platform.mkdir p }
-        @aruba.touch(name, options)
+        Aruba.platform.mkdir path
+      end
+
+      it "leaves the directory a directory" do
+        @aruba.touch(name)
+        expect(File.directory?(path)).to be true
       end
 
-      context "and the mtime should be set statically" do
-        let(:time) { Time.parse("2014-01-01 10:00:00") }
-        let(:options) { { mtime: Time.parse("2014-01-01 10:00:00") } }
+      it "sets the mtime if requested" do
+        time = Time.parse("2014-01-01 10:00:00")
+        @aruba.touch(name, mtime: time)
 
-        it_behaves_like "an existing directory"
-        it { Array(path).each { |p| expect(File.mtime(p)).to eq time } }
+        aggregate_failures do
+          expect(File.directory?(path)).to be true
+          expect(File.mtime(path)).to eq time
+        end
       end
     end
   end
@@ -208,30 +215,26 @@
 
   describe "#exist?" do
     context "when given a file" do
-      context "when it exists" do
-        before do
-          Aruba.platform.write_file(path, "")
-        end
+      it "returns true if the file exists" do
+        Aruba.platform.write_file(path, "")
 
-        it { expect(@aruba).to be_exist(name) }
+        expect(@aruba.exist?(name)).to be true
       end
 
-      context "when it does not exist" do
-        it { expect(@aruba).not_to be_exist(name) }
+      it "returns false if the file does not exist" do
+        expect(@aruba.exist?(name)).to be false
       end
     end
 
     context "when given a directory" do
-      context "when it exists" do
-        before do
-          Aruba.platform.mkdir(dir_path)
-        end
+      it "returns true if the directory exists" do
+        Aruba.platform.mkdir(dir_path)
 
-        it { expect(@aruba).to be_exist(dir_name) }
+        expect(@aruba.exist?(dir_name)).to be true
       end
 
-      context "when it does not exist" do
-        it { expect(@aruba).not_to be_exist(dir_name) }
+      it "returns false if the directory does not exist" do
+        expect(@aruba.exist?(dir_name)).to be false
       end
     end
   end
@@ -663,93 +666,93 @@ def actual_permissions
   end
 
   describe "#remove" do
-    let(:name) { "test.txt" }
-    let(:path) { File.join(@aruba.aruba.current_directory, name) }
     let(:options) { {} }
 
-    before do
-      @aruba.set_environment_variable "HOME", File.expand_path(@aruba.aruba.current_directory)
-    end
-
-    context "when given a file" do
-      context "when it exists" do
-        before do
-          Array(path).each { |it| File.open(File.expand_path(it), "w") { |f| f << "" } }
-
-          @aruba.remove(name, options)
-        end
+    context "when given an existing file" do
+      it "removes a single file" do
+        name = "test.txt"
+        path = File.join(@aruba.aruba.current_directory, name)
 
-        context "when is a single file" do
-          it_behaves_like "a non-existing file"
-        end
+        File.write(File.expand_path(path), "foo")
+        @aruba.remove(name)
 
-        context "when are multiple files" do
-          let(:name) { %w(file1 file2 file3) }
-          let(:path) { name.map { |it| File.join(@aruba.aruba.current_directory, it) } }
+        expect(File.exist?(path)).to be false
+      end
 
-          it_behaves_like "a non-existing file"
-        end
+      it "removes multiple files" do
+        names = %w(file1 file2 file3)
+        paths = names.map { |it| File.join(@aruba.aruba.current_directory, it) }
+        paths.each { |it| File.write(File.expand_path(it), "foo #{it}") }
 
-        context "when path contains ~" do
-          let(:string) { random_string }
-          let(:name) { File.join("~", string) }
-          let(:path) { File.join(@aruba.aruba.current_directory, string) }
-
-          it_behaves_like "a non-existing file"
+        @aruba.remove(names)
+        aggregate_failures do
+          paths.each do |path|
+            expect(File.exist?(path)).to be false
+          end
         end
       end
 
-      context "when it does not exist" do
-        before do
-          @aruba.remove(name, options)
-        end
+      it "interprets ~ as referencing the aruba home directory" do
+        string = random_string
+        name = File.join("~", string)
+        path = File.join(@aruba.aruba.config.home_directory, string)
+        File.write(File.expand_path(path), "foo")
 
-        context "when forced to delete the file" do
-          let(:options) { { force: true } }
+        @aruba.remove(name)
 
-          it_behaves_like "a non-existing file"
-        end
+        expect(File.exist?(path)).to be false
       end
     end
 
-    context "when given a directory" do
-      let(:name) { "test.d" }
+    context "when given an existing directory" do
+      it "removes a single directory" do
+        name = "test.d"
+        path = File.join(@aruba.aruba.current_directory, name)
+        Aruba.platform.mkdir path
 
-      context "when it exists" do
-        before do
-          Array(path).each { |it| Aruba.platform.mkdir it }
-          @aruba.remove(name, options)
-        end
+        @aruba.remove(name)
 
-        context "when is a single directory" do
-          it_behaves_like "a non-existing directory"
-        end
+        expect(File.exist?(path)).to be false
+      end
 
-        context "when are multiple directorys" do
-          let(:name) { %w(directory1 directory2 directory3) }
-          let(:path) { name.map { |it| File.join(@aruba.aruba.current_directory, it) } }
+      it "removes multiple directories" do
+        names = %w(directory1 directory2 directory3)
+        paths = names.map { |it| File.join(@aruba.aruba.current_directory, it) }
+        paths.each { |path| Aruba.platform.mkdir path }
 
-          it_behaves_like "a non-existing directory"
+        @aruba.remove(names)
+        aggregate_failures do
+          paths.each do |path|
+            expect(File.exist?(path)).to be false
+          end
         end
+      end
 
-        context "when path contains ~" do
-          let(:string) { random_string }
-          let(:name) { File.join("~", string) }
-          let(:path) { File.join(@aruba.aruba.current_directory, string) }
+      it "interprets ~ as referencing the aruba home directory" do
+        string = random_string
+        name = File.join("~", string)
+        path = File.join(@aruba.aruba.config.home_directory, string)
+        Aruba.platform.mkdir path
 
-          it_behaves_like "a non-existing directory"
-        end
+        @aruba.remove(name)
+
+        expect(File.exist?(path)).to be false
       end
+    end
 
-      context "when it does not exist" do
-        before do
-          @aruba.remove(name, options)
-        end
+    context "when given an item that does not exist" do
+      it "raises an error" do
+        name = "missing"
+        expect { @aruba.remove(name) }.to raise_error Errno::ENOENT
+      end
 
-        context "when forced to delete the directory" do
-          let(:options) { { force: true } }
+      it "raises no error when forced to delete the file" do
+        name = "missing"
+        path = File.join(@aruba.aruba.current_directory, name)
 
-          it_behaves_like "a non-existing directory"
+        aggregate_failures do
+          expect { @aruba.remove(name, force: true) }.not_to raise_error
+          expect(File.exist?(path)).to be false
         end
       end
     end
diff --git a/spec/aruba/configuration_spec.rb b/spec/aruba/configuration_spec.rb
index 05d84edb3..35e208976 100644
--- a/spec/aruba/configuration_spec.rb
+++ b/spec/aruba/configuration_spec.rb
@@ -6,7 +6,7 @@
   context "when is modified" do
     let(:config) { described_class.new }
 
-    it "won't allow bad values" do
+    it "does not allow bad values" do
       expect { config.fixtures_directories = [1, 2] }.to raise_error ParamContractError
     end
   end
diff --git a/spec/support/shared_examples/directory.rb b/spec/support/shared_examples/directory.rb
deleted file mode 100644
index 4e46b238f..000000000
--- a/spec/support/shared_examples/directory.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-shared_examples "an existing directory" do
-  it { Array(path).each { |p| expect(File).to be_directory(p) } }
-end
-
-shared_examples "a non-existing directory" do
-  it { Array(path).each { |p| expect(File).not_to be_exist(p) } }
-end
diff --git a/spec/support/shared_examples/file.rb b/spec/support/shared_examples/file.rb
deleted file mode 100644
index a53421832..000000000
--- a/spec/support/shared_examples/file.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-shared_examples "an existing file" do
-  it { Array(path).each { |p| expect(File).to be_file(p) } }
-end
-
-shared_examples "a non-existing file" do
-  it { Array(path).each { |p| expect(File).not_to be_exist(p) } }
-end