rubotium 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +1 -0
- data/bin/rubotium +26 -0
- data/lib/rubotium/adb/command.rb +21 -0
- data/lib/rubotium/adb/devices.rb +25 -0
- data/lib/rubotium/adb/install_command.rb +17 -0
- data/lib/rubotium/adb/instrumentation.rb +36 -0
- data/lib/rubotium/adb/shell.rb +30 -0
- data/lib/rubotium/adb/test_result_parser.rb +87 -0
- data/lib/rubotium/adb/uninstall_command.rb +17 -0
- data/lib/rubotium/adb.rb +13 -0
- data/lib/rubotium/apk/converter.rb +22 -0
- data/lib/rubotium/apk.rb +7 -0
- data/lib/rubotium/cmd.rb +17 -0
- data/lib/rubotium/device.rb +49 -0
- data/lib/rubotium/devices.rb +25 -0
- data/lib/rubotium/formatters/junit_formatter.rb +82 -0
- data/lib/rubotium/grouper.rb +40 -0
- data/lib/rubotium/jar_reader.rb +70 -0
- data/lib/rubotium/package.rb +36 -0
- data/lib/rubotium/runable_test.rb +11 -0
- data/lib/rubotium/test_case.rb +6 -0
- data/lib/rubotium/test_suite.rb +12 -0
- data/lib/rubotium/version.rb +3 -0
- data/lib/rubotium.rb +85 -0
- data/rubotium.gemspec +33 -0
- data/spec/fixtures/adb_devices_results.rb +23 -0
- data/spec/fixtures/adb_results.rb +60 -0
- data/spec/fixtures/jar_contents.rb +28 -0
- data/spec/fixtures/javap_classes.rb +52 -0
- data/spec/lib/rubotium/adb/adb_devices_spec.rb +25 -0
- data/spec/lib/rubotium/adb/adb_instrumentation_spec.rb +32 -0
- data/spec/lib/rubotium/adb/adb_result_parser_spec.rb +132 -0
- data/spec/lib/rubotium/adb/adb_shell_spec.rb +23 -0
- data/spec/lib/rubotium/devices_spec.rb +45 -0
- data/spec/lib/rubotium/formatters/junit_formatter_spec.rb +7 -0
- data/spec/lib/rubotium/grouper_spec.rb +56 -0
- data/spec/lib/rubotium/jar_reader_spec.rb +58 -0
- data/spec/lib/rubotium_spec.rb +13 -0
- data/spec/spec_helper.rb +20 -0
- metadata +256 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'android_apk'
|
2
|
+
|
3
|
+
module Rubotium
|
4
|
+
class Package
|
5
|
+
def initialize(package_path)
|
6
|
+
@package_path = package_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid?
|
10
|
+
!analyzed_package.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
analyzed_package.package_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def path
|
18
|
+
package_path
|
19
|
+
end
|
20
|
+
|
21
|
+
def version_name
|
22
|
+
analyzed_package.version_name
|
23
|
+
end
|
24
|
+
|
25
|
+
def version_code
|
26
|
+
analyzed_package.version_code
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
attr_reader :package_path
|
31
|
+
|
32
|
+
def analyzed_package
|
33
|
+
@analyzed_package ||= AndroidApk.analyze(package_path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/rubotium.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rubotium/version'
|
2
|
+
require 'rubotium/jar_reader'
|
3
|
+
require 'rubotium/adb'
|
4
|
+
require 'rubotium/apk'
|
5
|
+
require 'rubotium/cmd'
|
6
|
+
require 'rubotium/device'
|
7
|
+
require 'rubotium/devices'
|
8
|
+
require 'rubotium/formatters/junit_formatter'
|
9
|
+
require 'rubotium/grouper'
|
10
|
+
require 'rubotium/test_case'
|
11
|
+
require 'rubotium/test_suite'
|
12
|
+
require 'rubotium/runable_test'
|
13
|
+
require 'rubotium/package'
|
14
|
+
|
15
|
+
require 'parallel'
|
16
|
+
module Rubotium
|
17
|
+
class Error < StandardError; end
|
18
|
+
|
19
|
+
class NoDevicesError < Error; end
|
20
|
+
|
21
|
+
class NoMatchedDevicesError < Error; end
|
22
|
+
|
23
|
+
class NoTestSuiteError < Error; end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
def new(opts = {})
|
27
|
+
raise RuntimeError, "Empty configuration" if opts.empty?
|
28
|
+
startTime = Time.now
|
29
|
+
application_package = Rubotium::Package.new(opts[:app_apk_path])
|
30
|
+
tests_package = Rubotium::Package.new(opts[:tests_apk_path])
|
31
|
+
test_runner = opts[:runner]
|
32
|
+
|
33
|
+
if (opts[:tests_jar_path])
|
34
|
+
test_suites = JarReader.new(opts[:tests_jar_path]).get_tests
|
35
|
+
else
|
36
|
+
path_to_jar = File.join(Dir.mktmpdir, 'tests.jar')
|
37
|
+
begin
|
38
|
+
puts("Convertig dex to jar")
|
39
|
+
Rubotium::Apk::Converter.new(tests_package.path, path_to_jar).convert_to_jar
|
40
|
+
puts("Reading jar content")
|
41
|
+
test_suites = jar_reader = JarReader.new(path_to_jar).get_tests
|
42
|
+
ensure
|
43
|
+
FileUtils.remove_entry(path_to_jar)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
tests_count = 0
|
48
|
+
test_suites.each{|test_suite|
|
49
|
+
tests_count = tests_count + test_suite.test_cases.count
|
50
|
+
}
|
51
|
+
|
52
|
+
puts "There are #{test_suites.count} packages with tests in the Jar file"
|
53
|
+
puts "#{tests_count} tests to run"
|
54
|
+
|
55
|
+
devices = Devices.new(opts[:device_matcher]).all
|
56
|
+
test_suites = Grouper.new(test_suites, devices.count).create_groups
|
57
|
+
|
58
|
+
devices.each{|device|
|
59
|
+
device.uninstall application_package.name
|
60
|
+
device.install application_package.path
|
61
|
+
} if application_package.valid?
|
62
|
+
|
63
|
+
devices.each{|device|
|
64
|
+
device.uninstall tests_package.name
|
65
|
+
device.install tests_package.path
|
66
|
+
} if tests_package.valid?
|
67
|
+
|
68
|
+
devices.each_with_index{|device, index|
|
69
|
+
device.test_package_name = tests_package.name
|
70
|
+
device.test_runner_name = test_runner || "android.test.InstrumentationTestRunner"
|
71
|
+
device.testsuite = test_suites[index]
|
72
|
+
}
|
73
|
+
|
74
|
+
devices = Parallel.map(devices, :in_processes=> devices.count) {|device|
|
75
|
+
device.run_tests
|
76
|
+
device
|
77
|
+
}
|
78
|
+
|
79
|
+
puts "Tests took: #{Time.at(Time.now-startTime).utc.strftime("%H:%M:%S")}"
|
80
|
+
devices.each{|device|
|
81
|
+
Formatters::JunitFormatter.new(device.results, "#{device.serial}_#{opts[:report]}")
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/rubotium.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rubotium/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "rubotium"
|
8
|
+
spec.version = Rubotium::VERSION
|
9
|
+
spec.authors = ["Slawomir Smiechura"]
|
10
|
+
spec.email = ["ssmiech@gmail.com"]
|
11
|
+
spec.summary = "Run your Robotium tests with ease"
|
12
|
+
spec.description = "This gem allows to run Robotium tests in parallel on multiple devices"
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "simplecov", "0.8.2"
|
23
|
+
spec.add_development_dependency "coveralls", "0.7.0"
|
24
|
+
spec.add_development_dependency "rspec", "2.14.1"
|
25
|
+
spec.add_development_dependency "rspec-mocks"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
|
28
|
+
spec.add_dependency 'builder', '3.2.2'
|
29
|
+
spec.add_dependency 'trollop', '2.0'
|
30
|
+
spec.add_dependency 'parallel', '0.9.2'
|
31
|
+
spec.add_dependency 'dex2jar', '0.0.6'
|
32
|
+
spec.add_dependency 'android_apk', '0.7.0'
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Fixtures
|
2
|
+
class Adb
|
3
|
+
module Devices
|
4
|
+
class << self
|
5
|
+
def two_devices_attached_one_is_offline
|
6
|
+
"List of devices attached \nemulator-5554\toffline\nemulator-5556\tdevice\n\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
def two_devices_attached
|
10
|
+
"List of devices attached \nemulator-5554\tdevice\nemulator-5556\tdevice\n\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
def one_device_offline
|
14
|
+
"List of devices attached \nemulator-5554\toffline\n\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
def one_device
|
18
|
+
"List of devices attached \nemulator-5554\tdevice\n\n"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Fixtures
|
2
|
+
class Adb
|
3
|
+
class << self
|
4
|
+
def test_success
|
5
|
+
"\r\ncom.android.activity.resolve.facebook.ResolveTrackDeeplink:.\
|
6
|
+
\r\nTest results for RandomizingRunner=.\
|
7
|
+
\r\nTime: 5.873\
|
8
|
+
\r\n\r\nOK (1 test)\
|
9
|
+
\r\n\r\n\r\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_failure
|
13
|
+
"\r\ncom.android.activity.resolve.facebook.ResolveTrackDeeplink:\r\nFailure in testFacebookTrackDeeplink:\r\njunit.framework.ComparisonFailure: expected:<...h other on SoundClou[]> but was:<...h other on SoundClou[d]>\r\n\tat com.android.activity.resolve.facebook.ResolveTrackDeeplink.testFacebookTrackDeeplink(ResolveTrackDeeplink.java:22)\r\n\tat java.lang.reflect.Method.invokeNative(Native Method)\r\n\tat android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)\r\n\tat android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)\r\n\tat android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)\r\n\tat com.android.tests.ActivityTestCase.runTest(ActivityTestCase.java:91)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)\r\n\tat android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)\r\n\tat com.android.tests.RandomizingRunner.onStart(RandomizingRunner.java:11)\r\n\tat android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)\r\n\r\nTest results for RandomizingRunner=.F\r\nTime: 6.485\r\n\r\nFAILURES!!!\r\nTests run: 1, Failures: 1, Errors: 0\r\n\r\n\r\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_error
|
17
|
+
"\r\ncom.android.activity.resolve.facebook.ResolveTrackDeeplink:\r\nError in testFacebookTrackDeeplink:\r\njava.lang.NullPointerException\r\n\tat com.android.activity.resolve.facebook.ResolveTrackDeeplink.testFacebookTrackDeeplink(ResolveTrackDeeplink.java:22)\r\n\tat java.lang.reflect.Method.invokeNative(Native Method)\r\n\tat android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)\r\n\tat android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)\r\n\tat android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)\r\n\tat com.android.tests.ActivityTestCase.runTest(ActivityTestCase.java:91)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)\r\n\tat android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)\r\n\tat com.android.tests.RandomizingRunner.onStart(RandomizingRunner.java:11)\r\n\tat android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)\r\n\r\nTest results for RandomizingRunner=.E\r\nTime: 4.314\r\n\r\nFAILURES!!!\r\nTests run: 1, Failures: 0, Errors: 1\r\n\r\n\r\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_run_error
|
21
|
+
"\r\ncom.android.search.Search:INSTRUMENTATION_RESULT: shortMsg=java.lang.NullPointerException\
|
22
|
+
\r\nINSTRUMENTATION_RESULT: longMsg=java.lang.NullPointerException: An error occured while executing doInBackground()\
|
23
|
+
\r\nINSTRUMENTATION_CODE: 0\r\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_cannot_start_error
|
27
|
+
"INSTRUMENTATION_STATUS: id=ActivityManagerService\
|
28
|
+
\r\nINSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: ComponentInfo{com.android.tests/com.android.tests.RandomizingRunner}\
|
29
|
+
\r\nINSTRUMENTATION_STATUS_CODE: -1\
|
30
|
+
\\r\nandroid.util.AndroidException: INSTRUMENTATION_FAILED: com.android.tests/com.android.tests.RandomizingRunner\
|
31
|
+
\r\n\tat com.android.commands.am.Am.runInstrument(Am.java:616)\
|
32
|
+
\r\n\tat com.android.commands.am.Am.run(Am.java:118)\
|
33
|
+
\r\n\tat com.android.commands.am.Am.main(Am.java:81)\
|
34
|
+
\r\n\tat com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)\
|
35
|
+
\r\n\tat com.android.internal.os.RuntimeInit.main(RuntimeInit.java:235)\
|
36
|
+
\r\n\tat dalvik.system.NativeStart.main(Native Method)\r\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_failure_stack_trace
|
40
|
+
"junit.framework.ComparisonFailure: expected:<...h other on SoundClou[]> but was:<...h other on SoundClou[d]>\r\n\tat com.android.activity.resolve.facebook.ResolveTrackDeeplink.testFacebookTrackDeeplink(ResolveTrackDeeplink.java:22)\r\n\tat java.lang.reflect.Method.invokeNative(Native Method)\r\n\tat android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)\r\n\tat android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)\r\n\tat android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)\r\n\tat com.android.tests.ActivityTestCase.runTest(ActivityTestCase.java:91)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)\r\n\tat android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)\r\n\tat com.android.tests.RandomizingRunner.onStart(RandomizingRunner.java:11)\r\n\tat android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)"
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_error_stack_trace
|
44
|
+
"java.lang.NullPointerException\r\n\tat com.android.activity.resolve.facebook.ResolveTrackDeeplink.testFacebookTrackDeeplink(ResolveTrackDeeplink.java:22)\r\n\tat java.lang.reflect.Method.invokeNative(Native Method)\r\n\tat android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)\r\n\tat android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)\r\n\tat android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)\r\n\tat com.android.tests.ActivityTestCase.runTest(ActivityTestCase.java:91)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)\r\n\tat android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)\r\n\tat android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)\r\n\tat com.android.tests.RandomizingRunner.onStart(RandomizingRunner.java:11)\r\n\tat android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)"
|
45
|
+
end
|
46
|
+
|
47
|
+
def error_message
|
48
|
+
"java.lang.NullPointerException: An error occured while executing doInBackground()"
|
49
|
+
end
|
50
|
+
|
51
|
+
def passed_negative_time
|
52
|
+
"\r\ncom.android.explore.ExploreRecommendations:.\r\nTest results for RandomizingRunner=.\r\nTime: -53.656\r\n\r\nOK (1 test)\r\n\r\n\r\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
def system_crash
|
56
|
+
"\r\ncom.android.player.Player:INSTRUMENTATION_ABORTED: System has crashed.\r\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Fixtures
|
2
|
+
module JarContents
|
3
|
+
class << self
|
4
|
+
def duplicated_classes
|
5
|
+
<<-JAR_CONTENT
|
6
|
+
com/android/tests/Waiter$1$1.class
|
7
|
+
com/android/tests/Waiter$1.class
|
8
|
+
com/android/tests/Waiter$2.class
|
9
|
+
com/android/tests/Waiter$ByClassCondition.class
|
10
|
+
com/android/tests/Waiter$DrawerStateCondition.class
|
11
|
+
com/android/tests/Waiter$NoProgressBarCondition.class
|
12
|
+
com/android/tests/Waiter$NoTextCondition.class
|
13
|
+
com/android/tests/Waiter$PlayerPlayingCondition.class
|
14
|
+
com/android/tests/Waiter$VisibleElementCondition.class
|
15
|
+
com/android/tests/Waiter.class
|
16
|
+
JAR_CONTENT
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.multiple_classes
|
22
|
+
<<-JAR_CONTENT
|
23
|
+
com/android/screens/HomeScreen.class
|
24
|
+
com/android/auth/login/LoginFlowTest.class
|
25
|
+
JAR_CONTENT
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Fixtures
|
2
|
+
module JavaPClasses
|
3
|
+
class << self
|
4
|
+
def class_with_no_tests
|
5
|
+
<<-JAVAP
|
6
|
+
public class com.android.tests.Waiter extends java.lang.Object{
|
7
|
+
public final int NETWORK_TIMEOUT;
|
8
|
+
public final int TIMEOUT;
|
9
|
+
public com.android.tests.Han solo;
|
10
|
+
static {};
|
11
|
+
public com.android.tests.Waiter(com.android.tests.Han);
|
12
|
+
static java.lang.String access$300();
|
13
|
+
public void waitForActivity(java.lang.Class);
|
14
|
+
public boolean waitForContentAndRetryIfLoadingFailed();
|
15
|
+
public boolean waitForDrawerToClose();
|
16
|
+
public boolean waitForDrawerToOpen();
|
17
|
+
public boolean waitForElement(int);
|
18
|
+
public boolean waitForElement(android.view.View);
|
19
|
+
public boolean waitForElement(java.lang.Class);
|
20
|
+
public boolean waitForFragmentByTag(java.lang.String);
|
21
|
+
public boolean waitForItemCountToIncrease(android.widget.ListAdapter, int);
|
22
|
+
public void waitForLogInDialog();
|
23
|
+
public boolean waitForPlayerPlaying();
|
24
|
+
public void waitForText(java.lang.String);
|
25
|
+
public boolean waitForTextToDisappear(java.lang.String);
|
26
|
+
public void waitForViewId(int);
|
27
|
+
public boolean waitForWebViewToLoad(android.webkit.WebView);
|
28
|
+
}
|
29
|
+
JAVAP
|
30
|
+
end
|
31
|
+
|
32
|
+
def class_with_tests
|
33
|
+
<<-JAVAP
|
34
|
+
public class com.android.auth.login.LoginFlowTest extends com.android.auth.LoginTestCase{
|
35
|
+
public com.android.auth.login.LoginFlowTest();
|
36
|
+
public void ignore_testLoginWithFBApplication();
|
37
|
+
public void setUp() throws java.lang.Exception;
|
38
|
+
public void testGPlusLoginFlow();
|
39
|
+
public void testLoginAndLogout();
|
40
|
+
public void testLoginWithFacebookWebFlow() throws java.lang.Throwable;
|
41
|
+
public void testLoginWithWrongCredentials();
|
42
|
+
public void testNoGooglePlusAccountLogin();
|
43
|
+
public void testRecoverPassword() throws java.lang.Throwable;
|
44
|
+
public void testRecoverPasswordNoInput();
|
45
|
+
public void testSCUserLoginFlow();
|
46
|
+
}
|
47
|
+
JAVAP
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubotium::Adb::Devices do
|
4
|
+
let(:devices) { described_class.new }
|
5
|
+
|
6
|
+
it 'should return list of devices' do
|
7
|
+
Rubotium::CMD.stub(:run_command).and_return(Fixtures::Adb::Devices.two_devices_attached)
|
8
|
+
devices.list.should == ['emulator-5554', 'emulator-5556']
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should not return offline devices' do
|
12
|
+
Rubotium::CMD.stub(:run_command).and_return(Fixtures::Adb::Devices.two_devices_attached_one_is_offline)
|
13
|
+
devices.list.should == ['emulator-5556']
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should return one device' do
|
17
|
+
Rubotium::CMD.stub(:run_command).and_return(Fixtures::Adb::Devices.one_device)
|
18
|
+
devices.list.should == ['emulator-5554']
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should return zero devices if none are attached' do
|
22
|
+
Rubotium::CMD.stub(:run_command).and_return(Fixtures::Adb::Devices.one_device_offline)
|
23
|
+
devices.list.should == []
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubotium::Adb::Instrumentation do
|
4
|
+
let (:instr) { described_class }
|
5
|
+
let(:runable_test) {double(RunableTest)}
|
6
|
+
|
7
|
+
context 'running tests' do
|
8
|
+
let (:inst) { instr.new(" ") }
|
9
|
+
it 'should raise error if test runner name is not set' do
|
10
|
+
inst.test_package_name = "test_package"
|
11
|
+
expect { inst.run_test(runable_test) }.to raise_error (Rubotium::Adb::NoTestRunnerError)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should raise error if test package name is not set' do
|
15
|
+
inst.test_runner = "runner"
|
16
|
+
expect { inst.run_test(runable_test) }.to raise_error (Rubotium::Adb::NoTestPackageError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'runs correct test' do
|
20
|
+
runable_test.stub(:package_name).and_return("package")
|
21
|
+
runable_test.stub(:test_name).and_return("test")
|
22
|
+
inst.test_package_name = "package_name"
|
23
|
+
inst.test_runner = "TestRunner"
|
24
|
+
|
25
|
+
command = "am instrument -w -e class package#test package_name/TestRunner"
|
26
|
+
Rubotium::Adb::Shell.any_instance.should_receive(:run_command).with(command)
|
27
|
+
Rubotium::Adb::Shell.any_instance.stub(:run_command).and_return(Fixtures::Adb.test_success)
|
28
|
+
inst.run_test(runable_test)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubotium::Adb::TestResultParser do
|
4
|
+
let(:parser) { described_class }
|
5
|
+
|
6
|
+
context 'failed test' do
|
7
|
+
let(:parsed_result) { parser.new(Fixtures::Adb.test_failure, "", "") }
|
8
|
+
|
9
|
+
it 'should not be passed' do
|
10
|
+
parsed_result.should_not be_passed
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should be failed' do
|
14
|
+
parsed_result.should be_failed
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should not be errored' do
|
18
|
+
parsed_result.should_not be_errored
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should get the stack trace' do
|
22
|
+
parsed_result.stack_trace.should == Fixtures::Adb.test_failure_stack_trace
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should get test's duration time" do
|
26
|
+
parsed_result.time.should be_eql 6.485
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should not have error message' do
|
30
|
+
parsed_result.error_message.should be_empty
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'passed test' do
|
35
|
+
let(:parsed_result) { parser.new(Fixtures::Adb.test_success, "", "") }
|
36
|
+
|
37
|
+
it 'should be passed' do
|
38
|
+
parsed_result.should be_passed
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should not be failed' do
|
42
|
+
parsed_result.should_not be_failed
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not be errored' do
|
46
|
+
parsed_result.should_not be_errored
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should not have a stack trace' do
|
50
|
+
parsed_result.stack_trace.should be_empty
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should get test's duration" do
|
54
|
+
parsed_result.time.should be_eql 5.873
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should not have error message' do
|
58
|
+
parsed_result.error_message.should be_empty
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'error in test' do
|
63
|
+
let(:parsed_result) { parser.new(Fixtures::Adb.test_error, "", "") }
|
64
|
+
|
65
|
+
it 'should not be passed' do
|
66
|
+
parsed_result.should_not be_passed
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should be failed' do
|
70
|
+
parsed_result.should be_failed
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should not be errored' do
|
74
|
+
parsed_result.should_not be_errored
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should get the stack trace' do
|
78
|
+
parsed_result.stack_trace.should == Fixtures::Adb.test_error_stack_trace
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should get test's duration time" do
|
82
|
+
parsed_result.time.should be_eql 4.314
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should not have error message' do
|
86
|
+
parsed_result.error_message.should be_empty
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'run error' do
|
91
|
+
let(:parsed_result) { parser.new(Fixtures::Adb.test_run_error, "", "") }
|
92
|
+
|
93
|
+
it 'should not be passed' do
|
94
|
+
parsed_result.should_not be_passed
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should not be failed' do
|
98
|
+
parsed_result.should_not be_failed
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should be errored' do
|
102
|
+
parsed_result.should be_errored
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should not take time to execute' do
|
106
|
+
parsed_result.time.should be_eql 0
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should know the error reason' do
|
110
|
+
parsed_result.error_message.should be_eql Fixtures::Adb.error_message
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should not have a stack trace' do
|
114
|
+
parsed_result.stack_trace.should be_empty
|
115
|
+
end
|
116
|
+
end
|
117
|
+
context 'passed tests with negative time' do
|
118
|
+
let(:parsed_result) { parser.new(Fixtures::Adb.passed_negative_time, "", "") }
|
119
|
+
|
120
|
+
it 'should not be passed' do
|
121
|
+
parsed_result.time.should == 53.656
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context 'system crash' do
|
126
|
+
let(:parsed_result) { parser.new(Fixtures::Adb.system_crash, "", "") }
|
127
|
+
|
128
|
+
it 'should know the error reason' do
|
129
|
+
parsed_result.error_message.should == "System has crashed.\r"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubotium::Adb::Shell do
|
4
|
+
let(:shell) { described_class }
|
5
|
+
before { Rubotium::CMD.stub(:run_command) }
|
6
|
+
|
7
|
+
context 'with no device given' do
|
8
|
+
it 'should execute commands without device' do
|
9
|
+
shell.new(nil).send(:command).should == "adb shell"
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should execute commands if device string is empty' do
|
13
|
+
shell.new("").send(:command).should == "adb shell"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with given device' do
|
18
|
+
it 'should execute commands on a device' do
|
19
|
+
shell.new("12345").send(:command).should == "adb -s 12345 shell"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubotium::Devices do
|
4
|
+
let(:devices_class) {described_class}
|
5
|
+
|
6
|
+
before do
|
7
|
+
Rubotium::Device.stub(:new).and_return("Device_Instance")
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'given device' do
|
11
|
+
let(:devices) {devices_class.new('emulator')}
|
12
|
+
|
13
|
+
it 'should complain about device being not accessible' do
|
14
|
+
Rubotium::Adb::Devices.any_instance.stub(:list).and_return([])
|
15
|
+
expect { devices.all }.to raise_error(Rubotium::NoDevicesError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should complain about not matched devices' do
|
19
|
+
Rubotium::Adb::Devices.any_instance.stub(:list).and_return(['nexus'])
|
20
|
+
expect { devices.all }.to raise_error(Rubotium::NoMatchedDevicesError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return test runner per device' do
|
24
|
+
Rubotium::Adb::Devices.any_instance.stub(:list).and_return(['emulator'])
|
25
|
+
devices.all.should == [ "Device_Instance" ]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should match devices' do
|
29
|
+
Rubotium::Adb::Devices.any_instance.stub(:list).and_return(['emulator', 'amolator', 'nexus', 'emulatores111', '113242'])
|
30
|
+
devices.send(:matched_devices, 'emulator').should == ["emulator", "emulatores111"]
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'without device' do
|
36
|
+
let(:devices) { devices_class.new }
|
37
|
+
|
38
|
+
it 'should use all available devices' do
|
39
|
+
Rubotium::Adb::Devices.any_instance.stub(:list).and_return(['emulator', 'amolator', 'nexus', 'emulatores111', '113242'])
|
40
|
+
devices.all.should == ["Device_Instance", "Device_Instance", "Device_Instance", "Device_Instance", "Device_Instance"]
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|