Merge changes I405abf9d,I7652eaa0
* changes:
Minor adjustments to the audio analysis integration tests.
Creates a once-and-for-all solution to running all UTs.
diff --git a/acts/framework/tests/acts_unittest_suite.py b/acts/framework/tests/acts_unittest_suite.py
deleted file mode 100755
index a4a753f..0000000
--- a/acts/framework/tests/acts_unittest_suite.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2016 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-import unittest
-
-import acts_android_device_test
-import acts_asserts_test
-import acts_base_class_test
-import acts_host_utils_test
-import acts_logger_test
-import acts_records_test
-import acts_test_runner_test
-import acts_utils_test
-
-
-def compile_suite():
- test_classes_to_run = [
- acts_asserts_test.ActsAssertsTest,
- acts_base_class_test.ActsBaseClassTest,
- acts_test_runner_test.ActsTestRunnerTest,
- acts_android_device_test.ActsAndroidDeviceTest,
- acts_records_test.ActsRecordsTest,
- acts_utils_test.ByPassSetupWizardTests,
- acts_utils_test.ConcurrentActionsTest,
- acts_logger_test.ActsLoggerTest,
- acts_host_utils_test.ActsHostUtilsTest
- ]
-
- loader = unittest.TestLoader()
-
- suites_list = []
- for test_class in test_classes_to_run:
- suite = loader.loadTestsFromTestCase(test_class)
- suites_list.append(suite)
-
- big_suite = unittest.TestSuite(suites_list)
- return big_suite
-
-
-if __name__ == "__main__":
- # This is the entry point for running all ACTS unit tests.
- runner = unittest.TextTestRunner()
- results = runner.run(compile_suite())
- sys.exit(not results.wasSuccessful())
diff --git a/acts/framework/tests/audio_analysis_unittest.py b/acts/framework/tests/audio_analysis_integrationtest.py
similarity index 92%
rename from acts/framework/tests/audio_analysis_unittest.py
rename to acts/framework/tests/audio_analysis_integrationtest.py
index d90b822..b41e662 100644
--- a/acts/framework/tests/audio_analysis_unittest.py
+++ b/acts/framework/tests/audio_analysis_integrationtest.py
@@ -14,11 +14,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# Note: This test has been labelled as an integration test due to its use of
+# real data, and the five to six second execution time.
import logging
import numpy
import os
import unittest
+# TODO(markdr): Remove this after soundfile is added to setup.py
+import sys
+import mock
+sys.modules['soundfile'] = mock.Mock()
+
import acts.test_utils.audio_analysis_lib.audio_analysis as audio_analysis
import acts.test_utils.audio_analysis_lib.audio_data as audio_data
@@ -83,13 +90,13 @@
# Sort the peaks by values.
return sorted(results, key=lambda x: x[1], reverse=True)
- def testPeakDetection(self):
+ def test_peak_detection(self):
array = [0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 5, 3, 2, 1, 1, 1, 1, 1]
result = audio_analysis.peak_detection(array, 4)
golden_answer = [(12, 5), (4, 4)]
self.assertEqual(result, golden_answer)
- def testPeakDetectionLarge(self):
+ def test_peak_detection_large(self):
array = numpy.random.uniform(0, 1, 1000000)
window_size = 100
logging.debug('Test large array using dummy peak detection')
@@ -99,7 +106,7 @@
logging.debug('Compare the result')
self.assertEqual(dummy_answer, improved_answer)
- def testSpectralAnalysis(self):
+ def test_spectral_analysis(self):
rate = 48000
length_in_secs = 0.5
freq_1 = 490.0
@@ -123,7 +130,7 @@
self.assertTrue(
abs(results[0][1] / results[1][1] - coeff_1 / coeff_2) < 0.01)
- def testSpectralAnalysisRealData(self):
+ def test_spectral_snalysis_real_data(self):
"""This unittest checks the spectral analysis works on real data."""
file_path = os.path.join(
os.path.dirname(__file__), 'test_data', '1k_2k.raw')
@@ -142,7 +149,7 @@
abs(spectral[0][0] - golden_frequency[channel]) < 5,
'Dominant frequency is not correct')
- def testNotMeaningfulData(self):
+ def test_not_meaningful_data(self):
"""Checks that sepectral analysis handles un-meaningful data."""
rate = 48000
length_in_secs = 0.5
@@ -159,7 +166,7 @@
class NormalizeTest(unittest.TestCase):
- def testNormalize(self):
+ def test_normalize(self):
y = [1, 2, 3, 4, 5]
normalized_y = audio_analysis.normalize_signal(y, 10)
expected = numpy.array([0.1, 0.2, 0.3, 0.4, 0.5])
@@ -251,16 +258,16 @@
self.assertTrue(detected_secs <= expected_detected_range_secs[1])
self.assertTrue(detected_secs >= expected_detected_range_secs[0])
- def testGoodSignal(self):
+ def test_good_signal(self):
"""Sine wave signal with no noise or anomaly."""
self.check_no_anomaly()
- def testGoodSignalNoise(self):
+ def test_good_signal_noise(self):
"""Sine wave signal with noise."""
self.add_noise()
self.check_no_anomaly()
- def testZeroAnomaly(self):
+ def test_zero_anomaly(self):
"""Sine wave signal with no noise but with anomaly.
This test case simulates underrun in digital data where there will be
@@ -271,7 +278,7 @@
self.insert_anomaly()
self.check_anomaly()
- def testZeroAnomalyNoise(self):
+ def test_zero_anomaly_noise(self):
"""Sine wave signal with noise and anomaly.
This test case simulates underrun in analog data where there will be
@@ -283,7 +290,7 @@
self.add_noise()
self.check_anomaly()
- def testLowConstantAnomaly(self):
+ def test_low_constant_anomaly(self):
"""Sine wave signal with low constant anomaly.
The anomaly is one block of constant values.
@@ -293,7 +300,7 @@
self.insert_anomaly()
self.check_anomaly()
- def testLowConstantAnomalyNoise(self):
+ def test_low_constant_anomaly_noise(self):
"""Sine wave signal with low constant anomaly and noise.
The anomaly is one block of constant values.
@@ -304,7 +311,7 @@
self.add_noise()
self.check_anomaly()
- def testHighConstantAnomaly(self):
+ def test_high_constant_anomaly(self):
"""Sine wave signal with high constant anomaly.
The anomaly is one block of constant values.
@@ -314,7 +321,7 @@
self.insert_anomaly()
self.check_anomaly()
- def testHighConstantAnomalyNoise(self):
+ def test_high_constant_anomaly_noise(self):
"""Sine wave signal with high constant anomaly and noise.
The anomaly is one block of constant values.
@@ -325,7 +332,7 @@
self.add_noise()
self.check_anomaly()
- def testSkippedAnomaly(self):
+ def test_skipped_anomaly(self):
"""Sine wave signal with skipped anomaly.
The anomaly simulates the symptom where a block is skipped.
@@ -334,7 +341,7 @@
self.generate_skip_anomaly()
self.check_anomaly()
- def testSkippedAnomalyNoise(self):
+ def test_skipped_anomaly_noise(self):
"""Sine wave signal with skipped anomaly with noise.
The anomaly simulates the symptom where a block is skipped.
@@ -344,7 +351,7 @@
self.add_noise()
self.check_anomaly()
- def testEmptyData(self):
+ def test_empty_data(self):
"""Checks that anomaly detection rejects empty data."""
self.y = []
with self.assertRaises(audio_analysis.EmptyDataError):
diff --git a/acts/framework/tests/audio_quality_measurement_unittest.py b/acts/framework/tests/audio_quality_measurement_integrationtest.py
similarity index 93%
rename from acts/framework/tests/audio_quality_measurement_unittest.py
rename to acts/framework/tests/audio_quality_measurement_integrationtest.py
index 0166ce9..e6e0c70 100644
--- a/acts/framework/tests/audio_quality_measurement_unittest.py
+++ b/acts/framework/tests/audio_quality_measurement_integrationtest.py
@@ -14,15 +14,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import logging
+# Note: This test has been labelled as an integration test due to its use of
+# real data, and the 12+ second execution time. It also generates sine waves
+# during the test, rather than using data that has been pre-calculated.
+
import math
import numpy
import unittest
-import acts.test_utils.audio_analysis_lib.audio_data as audio_data
-import acts.test_utils.audio_analysis_lib.audio_analysis as audio_analysis
-import acts.test_utils.audio_analysis_lib.audio_quality_measurement as \
- audio_quality_measurement
+# TODO(markdr): Remove this after soundfile is added to setup.py
+import sys
+import mock
+sys.modules['soundfile'] = mock.Mock()
+
+import acts.test_utils.audio_analysis_lib.audio_quality_measurement as audio_quality_measurement
class NoiseLevelTest(unittest.TestCase):
@@ -30,7 +35,7 @@
"""Uses the same seed to generate noise for each test."""
numpy.random.seed(0)
- def testNoiseLevel(self):
+ def test_noise_level(self):
# Generates the standard sin wave with standard_noise portion of noise.
rate = 48000
length_in_secs = 2
@@ -61,7 +66,7 @@
class ErrorTest(unittest.TestCase):
- def testError(self):
+ def test_error(self):
value1 = [0.2, 0.4, 0.1, 0.01, 0.01, 0.01]
value2 = [0.3, 0.3, 0.08, 0.0095, 0.0098, 0.0099]
error = [0.5, 0.25, 0.2, 0.05, 0.02, 0.01]
@@ -138,7 +143,7 @@
self.y[j] = self.amplitude * (3 + numpy.random.uniform(-1, 1))
def generate_volume_changing(self):
- "Generates volume changing during playing."
+ """Generates volume changing during playing."""
start_time = [0.300, 1.400]
end_time = [0.600, 1.700]
for i in range(len(start_time)):
@@ -149,7 +154,7 @@
self.volume_changing = [+1, -1, +1, -1]
self.volume_changing_time = [0.3, 0.6, 1.4, 1.7]
- def testGoodSignal(self):
+ def test_good_signal(self):
"""Sine wave signal with no noise or artifacts."""
result = audio_quality_measurement.quality_measurement(self.y,
self.rate)
@@ -160,7 +165,7 @@
self.assertTrue(len(result['volume_changes']) == 0)
self.assertTrue(result['equivalent_noise_level'] < 0.005)
- def testGoodSignalNoise(self):
+ def test_good_signal_with_noise(self):
"""Sine wave signal with noise."""
self.add_noise()
result = audio_quality_measurement.quality_measurement(self.y,
@@ -170,10 +175,9 @@
self.assertTrue(len(result['artifacts']['delay_during_playback']) == 0)
self.assertTrue(len(result['artifacts']['burst_during_playback']) == 0)
self.assertTrue(len(result['volume_changes']) == 0)
- self.assertTrue(0.009 < result['equivalent_noise_level'] and
- result['equivalent_noise_level'] < 0.011)
+ self.assertTrue(0.009 < result['equivalent_noise_level'] < 0.011)
- def testDelay(self):
+ def test_delay(self):
"""Sine wave with delay during playing."""
self.generate_delay()
result = audio_quality_measurement.quality_measurement(self.y,
@@ -196,7 +200,7 @@
duration)
self.assertTrue(delta < 0.001)
- def testArtifactsBeforePlayback(self):
+ def test_artifacts_before_playback(self):
"""Sine wave with artifacts before playback."""
self.generate_artifacts_before_playback()
result = audio_quality_measurement.quality_measurement(self.y,
@@ -212,7 +216,7 @@
self.assertTrue(len(result['volume_changes']) == 0)
self.assertTrue(result['equivalent_noise_level'] < 0.005)
- def testArtifactsAfterPlayback(self):
+ def test_artifacts_after_playback(self):
"""Sine wave with artifacts after playback."""
self.generate_artifacts_after_playback()
result = audio_quality_measurement.quality_measurement(self.y,
@@ -228,7 +232,7 @@
self.assertTrue(len(result['volume_changes']) == 0)
self.assertTrue(result['equivalent_noise_level'] < 0.005)
- def testBurstDuringPlayback(self):
+ def test_burst_during_playback(self):
"""Sine wave with burst during playback."""
self.generate_burst_during_playback()
result = audio_quality_measurement.quality_measurement(self.y,
@@ -244,7 +248,7 @@
'burst_during_playback'][i])
self.assertTrue(delta < 0.002)
- def testVolumeChanging(self):
+ def test_volume_changing(self):
"""Sine wave with volume changing during playback."""
self.generate_volume_changing()
result = audio_quality_measurement.quality_measurement(self.y,
diff --git a/acts/framework/tests/controllers/android_lib/android_lib_unittest_bundle.py b/acts/framework/tests/controllers/android_lib/android_lib_unittest_bundle.py
deleted file mode 100755
index cf8e81e..0000000
--- a/acts/framework/tests/controllers/android_lib/android_lib_unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == '__main__':
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/controllers/sl4a_lib/test_suite.py b/acts/framework/tests/controllers/sl4a_lib/test_suite.py
deleted file mode 100755
index de6835c..0000000
--- a/acts/framework/tests/controllers/sl4a_lib/test_suite.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import sys
-import unittest
-
-import rpc_client_test
-import rpc_connection_test
-import sl4a_manager_test
-import sl4a_session_test
-
-
-def compile_suite():
- test_classes_to_run = [
- rpc_client_test.RpcClientTest,
- rpc_connection_test.RpcConnectionTest,
- sl4a_manager_test.Sl4aManagerFactoryTest,
- sl4a_manager_test.Sl4aManagerTest,
- sl4a_session_test.Sl4aSessionTest,
- ]
- loader = unittest.TestLoader()
-
- suites_list = []
- for test_class in test_classes_to_run:
- suite = loader.loadTestsFromTestCase(test_class)
- suites_list.append(suite)
-
- big_suite = unittest.TestSuite(suites_list)
- return big_suite
-
-
-if __name__ == "__main__":
- # This is the entry point for running all SL4A Lib unit tests.
- runner = unittest.TextTestRunner()
- results = runner.run(compile_suite())
- sys.exit(not results.wasSuccessful())
diff --git a/acts/framework/tests/event/event_unittest_bundle.py b/acts/framework/tests/event/event_unittest_bundle.py
deleted file mode 100755
index 56c3e09..0000000
--- a/acts/framework/tests/event/event_unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == '__main__':
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/libs/logging/logging_unittest_bundle.py b/acts/framework/tests/libs/logging/logging_unittest_bundle.py
deleted file mode 100755
index cf8e81e..0000000
--- a/acts/framework/tests/libs/logging/logging_unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == '__main__':
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/libs/metrics/unittest_bundle.py b/acts/framework/tests/libs/metrics/unittest_bundle.py
deleted file mode 100755
index 87d5bc5..0000000
--- a/acts/framework/tests/libs/metrics/unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == "__main__":
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/libs/ota/unittest_bundle.py b/acts/framework/tests/libs/ota/unittest_bundle.py
deleted file mode 100755
index 87d5bc5..0000000
--- a/acts/framework/tests/libs/ota/unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == "__main__":
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/libs/proc/proc_unittest_bundle.py b/acts/framework/tests/libs/proc/proc_unittest_bundle.py
deleted file mode 100755
index cf8e81e..0000000
--- a/acts/framework/tests/libs/proc/proc_unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2018 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == '__main__':
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/metrics/unittest_bundle.py b/acts/framework/tests/metrics/unittest_bundle.py
deleted file mode 100755
index 56c3e09..0000000
--- a/acts/framework/tests/metrics/unittest_bundle.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2017 - The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import sys
-import unittest
-
-
-def main():
- suite = unittest.TestLoader().discover(
- start_dir=os.path.dirname(__file__), pattern='*_test.py')
- return suite
-
-
-if __name__ == '__main__':
- test_suite = main()
- runner = unittest.TextTestRunner()
- test_run = runner.run(test_suite)
- sys.exit(not test_run.wasSuccessful())
diff --git a/acts/framework/tests/test_runner_test.py b/acts/framework/tests/test_runner_test.py
index 2ec3da4..066c855 100755
--- a/acts/framework/tests/test_runner_test.py
+++ b/acts/framework/tests/test_runner_test.py
@@ -14,11 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import shutil
import tempfile
import unittest
-import os
from mobly.config_parser import TestRunConfig
from mock import Mock
from mock import patch
@@ -122,5 +122,5 @@
expected_timestamp))
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/acts/framework/tests/test_suite.py b/acts/framework/tests/test_suite.py
new file mode 100755
index 0000000..d10586b
--- /dev/null
+++ b/acts/framework/tests/test_suite.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python3
+#
+# Copyright 2017 - The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import sys
+import tempfile
+import unittest
+import multiprocessing
+
+
+def run_tests(test_suite, output_file):
+ # Redirects stdout and stderr to the given output file.
+ stdout_fd = os.open(output_file, os.O_WRONLY | os.O_CREAT)
+ stderr_fd = os.dup(stdout_fd)
+ os.dup2(stdout_fd, 1)
+ os.dup2(stderr_fd, 2)
+ test_run = unittest.TextTestRunner(verbosity=2).run(test_suite)
+ return test_run.wasSuccessful()
+
+
+class TestResult(object):
+ def __init__(self, process_result, output_file, test_suite):
+ self.process_result = process_result
+ self.output_file = output_file
+ self.test_suite = test_suite
+
+
+def run_all_unit_tests():
+ # Due to some incredibly powerful black magic, running this twice
+ # causes the metrics/, test_utils/ and test_runner_test.py tests to load
+ # properly. They do no load properly the first time.
+ suite = unittest.TestLoader().discover(
+ start_dir=os.path.dirname(__file__), pattern='*_test.py')
+ suite = unittest.TestLoader().discover(
+ start_dir=os.path.dirname(__file__), pattern='*_test.py')
+
+ process_pool = multiprocessing.Pool(10)
+ output_dir = tempfile.mkdtemp()
+
+ results = []
+
+ for index, test in enumerate(suite._tests):
+ output_file = os.path.join(output_dir, 'test_%s.output' % index)
+ process_result = process_pool.apply_async(run_tests,
+ args=(test, output_file))
+ results.append(TestResult(process_result, output_file, test))
+
+ success = True
+ for index, result in enumerate(results):
+ try:
+ if not result.process_result.get(timeout=60):
+ success = False
+ print('Received the following test failure:')
+ with open(result.output_file, 'r') as out_file:
+ print(out_file.read())
+ except multiprocessing.TimeoutError:
+ success = False
+ print('The following test timed out: %r' % result.test_suite,
+ file=sys.stderr)
+ with open(result.output_file, 'r') as out_file:
+ print(out_file.read())
+
+ exit(not success)
+
+
+if __name__ == '__main__':
+ run_all_unit_tests()
diff --git a/acts/framework/tests/controllers/test_suite.py b/acts/framework/tests/test_utils/__init__.py
similarity index 100%
rename from acts/framework/tests/controllers/test_suite.py
rename to acts/framework/tests/test_utils/__init__.py
diff --git a/acts/framework/tests/controllers/test_suite.py b/acts/framework/tests/test_utils/instrumentation/__init__.py
similarity index 100%
copy from acts/framework/tests/controllers/test_suite.py
copy to acts/framework/tests/test_utils/instrumentation/__init__.py
diff --git a/acts/framework/tests/controllers/test_suite.py b/acts/framework/tests/test_utils/power/__init__.py
similarity index 100%
copy from acts/framework/tests/controllers/test_suite.py
copy to acts/framework/tests/test_utils/power/__init__.py
diff --git a/acts/framework/tests/controllers/test_suite.py b/acts/framework/tests/test_utils/power/tel/__init__.py
similarity index 100%
copy from acts/framework/tests/controllers/test_suite.py
copy to acts/framework/tests/test_utils/power/tel/__init__.py
diff --git a/acts/tests/meta/ActsUnitTest.py b/acts/tests/meta/ActsUnitTest.py
index 89db2c4..bcf50dd 100755
--- a/acts/tests/meta/ActsUnitTest.py
+++ b/acts/tests/meta/ActsUnitTest.py
@@ -23,46 +23,8 @@
from acts import base_test
from acts import signals
-# The files under acts/framework to consider as unit tests.
-UNITTEST_FILES = [
- 'tests/acts_adb_test.py',
- 'tests/acts_android_device_test.py',
- 'tests/acts_asserts_test.py',
- 'tests/acts_base_class_test.py',
- 'tests/acts_context_test.py',
- 'tests/acts_error_test.py',
- 'tests/acts_host_utils_test.py',
- 'tests/acts_import_test_utils_test.py',
- 'tests/acts_import_unit_test.py',
- 'tests/acts_job_test.py',
- 'tests/libs/ota/unittest_bundle.py',
- 'tests/acts_logger_test.py',
- 'tests/libs/metrics/unittest_bundle.py',
- 'tests/acts_records_test.py',
- 'tests/acts_relay_controller_test.py',
- 'tests/acts_test_runner_test.py',
- 'tests/acts_unittest_suite.py',
- 'tests/acts_utils_test.py',
- 'tests/controllers/android_lib/android_lib_unittest_bundle.py',
- 'tests/event/event_unittest_bundle.py',
- 'tests/test_utils/instrumentation/unit_test_suite.py',
- 'tests/libs/logging/logging_unittest_bundle.py',
- 'tests/metrics/unittest_bundle.py',
- 'tests/libs/proc/proc_unittest_bundle.py',
- 'tests/controllers/sl4a_lib/test_suite.py',
- 'tests/test_runner_test.py',
- 'tests/libs/version_selector_test.py',
- 'tests/test_utils/power/tel/lab/consume_parameter_test.py',
- 'tests/test_utils/power/tel/lab/ensure_valid_calibration_table_test.py',
- 'tests/test_utils/power/tel/lab/init_simulation_test.py',
- 'tests/test_utils/power/tel/lab/initialize_simulator_test.py',
- 'tests/test_utils/power/tel/lab/save_summary_to_file_test.py',
- 'tests/test_utils/power/tel/lab/power_tel_traffic_e2e_test.py'
-]
-
-# The number of seconds to wait before considering the unit test to have timed
-# out.
-UNITTEST_TIMEOUT = 60
+# The number of seconds to wait before considering the test to have timed out.
+TIMEOUT = 60
class ActsUnitTest(base_test.BaseTestClass):
@@ -71,47 +33,39 @@
This is a hack to run the ACTS unit tests through CI. Please use the main
function below if you need to run these tests.
"""
+
def test_units(self):
- """Runs all the ACTS unit tests in parallel."""
- acts_unittest_path = os.path.dirname(acts.__path__[0])
- test_processes = []
+ """Runs all the ACTS unit tests in test_suite.py."""
+ test_script = os.path.join(os.path.dirname(acts.__path__[0]),
+ 'tests/test_suite.py')
+ test_process = subprocess.Popen([sys.executable, test_script],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
- fail_test = False
+ killed = False
+ try:
+ stdout, _ = test_process.communicate(timeout=TIMEOUT)
+ except subprocess.TimeoutExpired:
+ killed = True
+ self.log.error('Test %s timed out after %s seconds.' %
+ (test_process.args, TIMEOUT))
+ test_process.kill()
+ stdout, _ = test_process.communicate()
- for unittest_file in UNITTEST_FILES:
- file_path = os.path.join(acts_unittest_path, unittest_file)
- test_processes.append(
- subprocess.Popen([sys.executable, file_path],
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT))
-
- for test_process in test_processes:
- killed = False
- try:
- stdout, _ = test_process.communicate(timeout=UNITTEST_TIMEOUT)
- except subprocess.TimeoutExpired:
- killed = True
- self.log.error('Unit test %s timed out after %s seconds.' %
- (test_process.args, UNITTEST_TIMEOUT))
- test_process.kill()
- stdout, _ = test_process.communicate()
- if test_process.returncode != 0 or killed:
- self.log.error('=' * 79)
- self.log.error('Unit Test %s failed with error %s.' %
- (test_process.args, test_process.returncode))
- self.log.error('=' * 79)
- self.log.error('Failure for `%s`:\n%s' %
- (test_process.args,
- stdout.decode('utf-8', errors='replace')))
- fail_test = True
- else:
- self.log.debug('Output for `%s`:\n%s' %
- (test_process.args,
- stdout.decode('utf-8', errors='replace')))
-
- if fail_test:
+ if test_process.returncode != 0 or killed:
+ self.log.error('=' * 79)
+ self.log.error('Test %s failed with error %s.' %
+ (test_process.args, test_process.returncode))
+ self.log.error('=' * 79)
+ self.log.error('Failure for `%s`:\n%s' %
+ (test_process.args,
+ stdout.decode('utf-8', errors='replace')))
raise signals.TestFailure(
'One or more unit tests failed. See the logs.')
+ else:
+ self.log.debug('Output for `%s`:\n%s' %
+ (test_process.args,
+ stdout.decode('utf-8', errors='replace')))
def main():