diff --git a/CHANGELOG b/CHANGELOG index e2095c1..897bab0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,10 @@ +0.1.9 +* Fix Logger problem, caused by missing FORMAT definition +* Add feature 'Print available free devices' +* Set unlimited device run & screenshot downloads +* Correct help text for screenshots download +* Refactor test run download feature to download all files available for the test run + 0.1.8 * Fix file download for Linux and Mac machines. diff --git a/README.md b/README.md index d49e57c..fba1938 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,23 @@ Python client for Testdroid Cloud APIv2 ======================================= +Dependencies +----- + +For Linux installatin you need Python dev package. + +Ubuntu +`sudo apt-get install python-dev` + Command line ----- Install it with: `sudo pip install testdroid` +Upgrade it with: +`sudo pip install testdroid --upgrade` + Usage ----- @@ -45,3 +56,8 @@ Usage `testdroid` +Troubleshooting +----- + +If you see Pillow error messages on Linux you are most likely missing python-dev, see dependencies. + diff --git a/setup.py b/setup.py index 0f0adb5..cd357bc 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ 'Topic :: Software Development', 'Intended Audience :: Developers'], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers keywords='testdroid rest api client', - author='Henri Kivelä , Sakari Rautiainen , Teppo Malinen ', + author='Henri Kivelä , Sakari Rautiainen , Teppo Malinen , Jarno Tuovinen ', author_email='info@bitbar.com', url='http://www.testdroid.com', license='Apache License v2.0', diff --git a/testdroid/__init__.py b/testdroid/__init__.py index 4a08a64..4fcf5c1 100755 --- a/testdroid/__init__.py +++ b/testdroid/__init__.py @@ -8,7 +8,12 @@ from datetime import datetime __version__ = '0.1.9.dev' -logging.basicConfig(format=FORMAT) +try: + logging.basicConfig(format=FORMAT) +except Exception, e: + print "Warning: %s. Using FORMAT='%s(message)s.'" % (e, "%s") + logging.basicConfig(format="%(message)s") + logger = logging.getLogger('testdroid') logger.setLevel(logging.INFO) @@ -243,7 +248,7 @@ def get_device_groups(self): """ Returns list of devices """ def get_devices(self, limit=0): - return self.get("devices?limit=%s" % (limit)) + return self.get(path = "devices", payload = {'limit': limit}) """ Print device groups """ @@ -251,6 +256,39 @@ def print_device_groups(self): for device_group in self.get_device_groups()['data']: print "%s %s %s %s devices" % (str(device_group['id']).ljust(12), device_group['displayName'].ljust(30), device_group['osType'].ljust(10), device_group['deviceCount']) + """ Print available free Android devices + """ + def print_available_free_android_devices(self): + print "" + print "Available Free Android Devices" + print "------------------------------" + + for device in self.get_devices()['data']: + if device['creditsPrice'] == 0 and device['locked'] == False and device['osType'] == "ANDROID": + print device['displayName'] + + print "" + + """ Print available free iOS devices + """ + def print_available_free_ios_devices(self): + print "" + print "Available Free iOS Devices" + print "--------------------------" + + for device in self.get_devices()['data']: + if device['creditsPrice'] == 0 and device['locked'] == False and device['osType'] == "IOS": + print device['displayName'] + + print "" + + """ Print available free devices + """ + def print_available_free_devices(self): + self.print_available_free_android_devices() + self.print_available_free_ios_devices() + + """ Create a project """ def create_project(self, project_name, project_type): @@ -437,7 +475,7 @@ def stop_device_session(self, device_session_id): """ Get all test runs for a project """ def get_project_test_runs(self, project_id, limit=20): - return self.get("me/projects/%s/runs?limit=%s" % (project_id, limit)) + return self.get(path = "me/projects/%s/runs" % (project_id), payload = {'limit': limit}) """ Print test runs of a project to console """ @@ -453,43 +491,50 @@ def get_test_run(self, project_id, test_run_id): """ Return device runs for a project """ - def get_device_runs(self, project_id, test_run_id, limit=1000): - return self.get("me/projects/%s/runs/%s/device-runs?limit=%s" % (project_id, test_run_id, limit)) + def get_device_runs(self, project_id, test_run_id, limit=0): + return self.get(path = "me/projects/%s/runs/%s/device-runs" % (project_id, test_run_id), payload = {'limit': limit}) """ Downloads screenshots list for a device run """ - def get_device_run_screenshots_list(self, project_id, test_run_id, device_run_id): - return self.get("me/projects/%s/runs/%s/device-runs/%s/screenshots" % (project_id, test_run_id, device_run_id)) + def get_device_run_screenshots_list(self, project_id, test_run_id, device_run_id, limit=0): + return self.get("me/projects/%s/runs/%s/device-runs/%s/screenshots" % (project_id, test_run_id, device_run_id), payload = {'limit': limit}) - """ Downloads test run results to a directory hierarchy + """ Downloads test run files to a directory hierarchy """ def download_test_run(self, project_id, test_run_id): test_run = self.get_test_run(project_id, test_run_id) device_runs = self.get_device_runs(project_id, test_run_id) - logger.info("Test run %s: \"%s\" has %s device runs:" % (test_run['id'], test_run['displayName'], len(device_runs['data']))) - for device_run in device_runs['data']: - logger.info("%s \"%s\" %s" % (device_run['id'], device_run['device']['displayName'], device_run['currentState']['status'])) - logger.info(""); + logger.info("") + logger.info("Test run %s: \"%s\" has %s device runs:" % (test_run['id'], test_run['displayName'], len(device_runs['data']))) for device_run in device_runs['data']: - if device_run['currentState']['status'] == "SUCCEEDED": - directory = "%s-%s/%d-%s" % (test_run['id'], test_run['displayName'], device_run['id'], device_run['device']['displayName']) - - filenames = ['junit.xml', 'logs', 'result-data.zip'] - - for filename in filenames: - full_path = "%s/%s" % (directory, filename) - if not os.path.exists(directory): - os.makedirs(directory) - url = "me/projects/%s/runs/%d/device-runs/%d/%s" % (project_id, test_run['id'], device_run['id'], filename) - - prog = DownloadProgressBar() - self.download(url, full_path, callback=lambda pos, total: prog.update(int(pos), int(total))) - print - + run_status = device_run['currentState']['status'] + logger.info("") + logger.info("%s \"%s\" %s" % (device_run['id'], device_run['device']['displayName'], run_status)) + + if run_status in ("SUCCEEDED", "FAILED"): + directory = "%s-%s/%d-%s" % (test_run_id, test_run['displayName'], device_run['id'], device_run['device']['displayName']) + session_id = device_run['deviceSessionId'] + files = self.get("me/projects/%s/runs/%s/device-sessions/%s/output-file-set/files" % (project_id, test_run_id, session_id)) + for file in files['data']: + if file['state'] == "READY": + full_path = "%s/%s" % (directory, file['name']) + if not os.path.exists(directory): + os.makedirs(directory) + + url = "me/files/%s/file" % (file['id']) + prog = DownloadProgressBar() + self.download(url, full_path, callback=lambda pos, total: prog.update(int(pos), int(total))) + print + else: + logger.info("File %s is not ready" % file['name']) + if( len(files['data']) == 0 ): + logger.info("No files to download") + logger.info("") else: - logger.info("Device %s has not finished - skipping" % device_run['device']['displayName']) + logger.info("Device run is not ended - Skipping file downloads") + logger.info("") """ Downloads test run screenshots """ @@ -546,6 +591,7 @@ def format_epilog(self, formatter): Commands: me Get user details + available-free-devices Print list of currently available free devices device-groups Get list of your device groups create-project Create a project Type is one of: @@ -579,9 +625,9 @@ def format_epilog(self, formatter): current directory in a structure: [test-run-id]/[device-run-id]-[device-name]/files... download-test-screenshots - Download test run data. Data will be downloaded to + Download test run screenshots. Screenshots will be downloaded to current directory in a structure: - [test-run-id]/[device-run-id]-[device-name]/files... + [test-run-id]/[device-run-id]-[device-name]/screenshots/... """ parser = MyParser(usage=usage, description=description, epilog=epilog, version="%s %s" % ("%prog", __version__)) @@ -601,6 +647,7 @@ def get_commands(self): commands = { "me": self.get_me, "device-groups": self.print_device_groups, + "available-free-devices": self.print_available_free_devices, "projects": self.print_projects, "create-project": self.create_project, "delete-project": self.delete_project,