Best Python code snippet using tempest_python
shares_client.py
Source:shares_client.py
...64 if share_type_id:65 post_body["share"]["share_type"] = share_type_id66 body = json.dumps(post_body)67 resp, body = self.post("shares", body)68 self.expected_success(200, resp.status)69 return self._parse_resp(body)70 def delete_share(self, share_id):71 resp, body = self.delete("shares/%s" % share_id)72 self.expected_success(202, resp.status)73 return body74 def manage_share(self, service_host, protocol, export_path,75 share_type_id, name=None, description=None):76 post_body = {77 "share": {78 "export_path": export_path,79 "service_host": service_host,80 "protocol": protocol,81 "share_type": share_type_id,82 "name": name,83 "description": description,84 }85 }86 body = json.dumps(post_body)87 resp, body = self.post("os-share-manage", body)88 self.expected_success(200, resp.status)89 return self._parse_resp(body)90 def unmanage_share(self, share_id):91 resp, body = self.post(92 "os-share-unmanage/%s/unmanage" % share_id, None)93 self.expected_success(202, resp.status)94 return body95 def list_shares(self, detailed=False, params=None):96 """Get list of shares w/o filters."""97 uri = 'shares/detail' if detailed else 'shares'98 uri += '?%s' % urlparse.urlencode(params) if params else ''99 resp, body = self.get(uri)100 self.expected_success(200, resp.status)101 return self._parse_resp(body)102 def list_shares_with_detail(self, params=None):103 """Get detailed list of shares w/o filters."""104 return self.list_shares(detailed=True, params=params)105 def get_share(self, share_id):106 resp, body = self.get("shares/%s" % share_id)107 self.expected_success(200, resp.status)108 return self._parse_resp(body)109 def create_access_rule(self, share_id, access_type="ip",110 access_to="0.0.0.0", access_level=None):111 post_body = {112 "os-allow_access": {113 "access_type": access_type,114 "access_to": access_to,115 "access_level": access_level,116 }117 }118 body = json.dumps(post_body)119 resp, body = self.post("shares/%s/action" % share_id, body)120 self.expected_success(200, resp.status)121 return self._parse_resp(body)122 def list_access_rules(self, share_id):123 body = {"os-access_list": None}124 resp, body = self.post("shares/%s/action" % share_id, json.dumps(body))125 self.expected_success(200, resp.status)126 return self._parse_resp(body)127 def delete_access_rule(self, share_id, rule_id):128 post_body = {129 "os-deny_access": {130 "access_id": rule_id,131 }132 }133 body = json.dumps(post_body)134 resp, body = self.post("shares/%s/action" % share_id, body)135 self.expected_success(202, resp.status)136 return body137 def extend_share(self, share_id, new_size):138 post_body = {139 "os-extend": {140 "new_size": new_size,141 }142 }143 body = json.dumps(post_body)144 resp, body = self.post("shares/%s/action" % share_id, body)145 self.expected_success(202, resp.status)146 return body147 def shrink_share(self, share_id, new_size):148 post_body = {149 "os-shrink": {150 "new_size": new_size,151 }152 }153 body = json.dumps(post_body)154 resp, body = self.post("shares/%s/action" % share_id, body)155 self.expected_success(202, resp.status)156 return body157 def create_snapshot(self, share_id, name=None, description=None,158 force=False):159 if name is None:160 name = data_utils.rand_name("tempest-created-share-snap")161 if description is None:162 description = data_utils.rand_name(163 "tempest-created-share-snap-desc")164 post_body = {165 "snapshot": {166 "name": name,167 "force": force,168 "description": description,169 "share_id": share_id,170 }171 }172 body = json.dumps(post_body)173 resp, body = self.post("snapshots", body)174 self.expected_success(202, resp.status)175 return self._parse_resp(body)176 def get_snapshot(self, snapshot_id):177 resp, body = self.get("snapshots/%s" % snapshot_id)178 self.expected_success(200, resp.status)179 return self._parse_resp(body)180 def list_snapshots(self, detailed=False, params=None):181 """Get list of share snapshots w/o filters."""182 uri = 'snapshots/detail' if detailed else 'snapshots'183 uri += '?%s' % urlparse.urlencode(params) if params else ''184 resp, body = self.get(uri)185 self.expected_success(200, resp.status)186 return self._parse_resp(body)187 def list_snapshots_with_detail(self, params=None):188 """Get detailed list of share snapshots w/o filters."""189 return self.list_snapshots(detailed=True, params=params)190 def delete_snapshot(self, snap_id):191 resp, body = self.delete("snapshots/%s" % snap_id)192 self.expected_success(202, resp.status)193 return body194 def wait_for_share_status(self, share_id, status):195 """Waits for a share to reach a given status."""196 body = self.get_share(share_id)197 share_name = body['name']198 share_status = body['status']199 start = int(time.time())200 while share_status != status:201 time.sleep(self.build_interval)202 body = self.get_share(share_id)203 share_status = body['status']204 if share_status == status:205 return206 elif 'error' in share_status.lower():207 raise share_exceptions.ShareBuildErrorException(208 share_id=share_id)209 if int(time.time()) - start >= self.build_timeout:210 message = ('Share %s failed to reach %s status within '211 'the required time (%s s).' %212 (share_name, status, self.build_timeout))213 raise exceptions.TimeoutException(message)214 def wait_for_snapshot_status(self, snapshot_id, status):215 """Waits for a snapshot to reach a given status."""216 body = self.get_snapshot(snapshot_id)217 snapshot_name = body['name']218 snapshot_status = body['status']219 start = int(time.time())220 while snapshot_status != status:221 time.sleep(self.build_interval)222 body = self.get_snapshot(snapshot_id)223 snapshot_status = body['status']224 if 'error' in snapshot_status:225 raise share_exceptions.SnapshotBuildErrorException(226 snapshot_id=snapshot_id)227 if int(time.time()) - start >= self.build_timeout:228 message = ('Share Snapshot %s failed to reach %s status '229 'within the required time (%s s).' %230 (snapshot_name, status, self.build_timeout))231 raise exceptions.TimeoutException(message)232 def wait_for_access_rule_status(self, share_id, rule_id, status):233 """Waits for an access rule to reach a given status."""234 rule_status = "new"235 start = int(time.time())236 while rule_status != status:237 time.sleep(self.build_interval)238 rules = self.list_access_rules(share_id)239 for rule in rules:240 if rule["id"] in rule_id:241 rule_status = rule['state']242 break243 if 'error' in rule_status:244 raise share_exceptions.AccessRuleBuildErrorException(245 rule_id=rule_id)246 if int(time.time()) - start >= self.build_timeout:247 message = ('Share Access Rule %s failed to reach %s status '248 'within the required time (%s s).' %249 (rule_id, status, self.build_timeout))250 raise exceptions.TimeoutException(message)251 def default_quotas(self, tenant_id):252 resp, body = self.get("os-quota-sets/%s/defaults" % tenant_id)253 self.expected_success(200, resp.status)254 return self._parse_resp(body)255 def show_quotas(self, tenant_id, user_id=None):256 uri = "os-quota-sets/%s" % tenant_id257 if user_id is not None:258 uri += "?user_id=%s" % user_id259 resp, body = self.get(uri)260 self.expected_success(200, resp.status)261 return self._parse_resp(body)262 def reset_quotas(self, tenant_id, user_id=None):263 uri = "os-quota-sets/%s" % tenant_id264 if user_id is not None:265 uri += "?user_id=%s" % user_id266 resp, body = self.delete(uri)267 self.expected_success(202, resp.status)268 return body269 def update_quotas(self, tenant_id, user_id=None, shares=None,270 snapshots=None, gigabytes=None, snapshot_gigabytes=None,271 share_networks=None, force=True):272 uri = "os-quota-sets/%s" % tenant_id273 if user_id is not None:274 uri += "?user_id=%s" % user_id275 put_body = {"tenant_id": tenant_id}276 if force:277 put_body["force"] = "true"278 if shares is not None:279 put_body["shares"] = shares280 if snapshots is not None:281 put_body["snapshots"] = snapshots282 if gigabytes is not None:283 put_body["gigabytes"] = gigabytes284 if snapshot_gigabytes is not None:285 put_body["snapshot_gigabytes"] = snapshot_gigabytes286 if share_networks is not None:287 put_body["share_networks"] = share_networks288 put_body = json.dumps({"quota_set": put_body})289 resp, body = self.put(uri, put_body)290 self.expected_success(200, resp.status)291 return self._parse_resp(body)292 def get_limits(self):293 resp, body = self.get("limits")294 self.expected_success(200, resp.status)295 return self._parse_resp(body)296 def is_resource_deleted(self, *args, **kwargs):297 """Verifies whether provided resource deleted or not.298 :param kwargs: dict with expected keys 'share_id', 'snapshot_id',299 :param kwargs: 'sn_id', 'ss_id', 'vt_id' and 'server_id'300 :raises share_exceptions.InvalidResource301 """302 if "share_id" in kwargs:303 if "rule_id" in kwargs:304 rule_id = kwargs.get("rule_id")305 share_id = kwargs.get("share_id")306 rules = self.list_access_rules(share_id)307 for rule in rules:308 if rule["id"] == rule_id:309 return False310 return True311 else:312 return self._is_resource_deleted(313 self.get_share, kwargs.get("share_id"))314 elif "snapshot_id" in kwargs:315 return self._is_resource_deleted(316 self.get_snapshot, kwargs.get("snapshot_id"))317 elif "sn_id" in kwargs:318 return self._is_resource_deleted(319 self.get_share_network, kwargs.get("sn_id"))320 elif "ss_id" in kwargs:321 return self._is_resource_deleted(322 self.get_security_service, kwargs.get("ss_id"))323 elif "vt_id" in kwargs:324 return self._is_resource_deleted(325 self.get_volume_type, kwargs.get("vt_id"))326 elif "st_id" in kwargs:327 return self._is_resource_deleted(328 self.get_share_type, kwargs.get("st_id"))329 elif "server_id" in kwargs:330 return self._is_resource_deleted(331 self.show_share_server, kwargs.get("server_id"))332 else:333 raise share_exceptions.InvalidResource(334 message=six.text_type(kwargs))335 def _is_resource_deleted(self, func, res_id):336 try:337 res = func(res_id)338 except exceptions.NotFound:339 return True340 if res.get('status') in ['error_deleting', 'error']:341 # Resource has "error_deleting" status and can not be deleted.342 resource_type = func.__name__.split('_', 1)[-1]343 raise share_exceptions.ResourceReleaseFailed(344 res_type=resource_type, res_id=res_id)345 return False346 def wait_for_resource_deletion(self, *args, **kwargs):347 """Waits for a resource to be deleted."""348 start_time = int(time.time())349 while True:350 if self.is_resource_deleted(*args, **kwargs):351 return352 if int(time.time()) - start_time >= self.build_timeout:353 raise exceptions.TimeoutException354 time.sleep(self.build_interval)355 def list_extensions(self):356 resp, extensions = self.get("extensions")357 self.expected_success(200, resp.status)358 return self._parse_resp(extensions)359 def update_share(self, share_id, name=None, desc=None, is_public=None):360 body = {"share": {}}361 if name is not None:362 body["share"].update({"display_name": name})363 if desc is not None:364 body["share"].update({"display_description": desc})365 if is_public is not None:366 body["share"].update({"is_public": is_public})367 body = json.dumps(body)368 resp, body = self.put("shares/%s" % share_id, body)369 self.expected_success(200, resp.status)370 return self._parse_resp(body)371 def rename_snapshot(self, snapshot_id, name, desc=None):372 body = {"snapshot": {"display_name": name}}373 if desc is not None:374 body["snapshot"].update({"display_description": desc})375 body = json.dumps(body)376 resp, body = self.put("snapshots/%s" % snapshot_id, body)377 self.expected_success(200, resp.status)378 return self._parse_resp(body)379 def reset_state(self, s_id, status="error", s_type="shares"):380 """Resets the state of a share or a snapshot.381 status: available, error, creating, deleting, error_deleting382 s_type: shares, snapshots383 """384 body = {"os-reset_status": {"status": status}}385 body = json.dumps(body)386 resp, body = self.post("%s/%s/action" % (s_type, s_id), body)387 self.expected_success(202, resp.status)388 return body389 def force_delete(self, s_id, s_type="shares"):390 """Force delete share or snapshot.391 s_type: shares, snapshots392 """393 body = {"os-force_delete": None}394 body = json.dumps(body)395 resp, body = self.post("%s/%s/action" % (s_type, s_id), body)396 self.expected_success(202, resp.status)397 return body398###############399 def list_services(self, params=None):400 """List services."""401 uri = 'os-services'402 if params:403 uri += '?%s' % urlparse.urlencode(params)404 resp, body = self.get(uri)405 self.expected_success(200, resp.status)406 return self._parse_resp(body)407###############408 def _update_metadata(self, share_id, metadata=None, method="post"):409 uri = "shares/%s/metadata" % share_id410 if metadata is None:411 metadata = {}412 post_body = {"metadata": metadata}413 body = json.dumps(post_body)414 if method is "post":415 resp, metadata = self.post(uri, body)416 if method is "put":417 resp, metadata = self.put(uri, body)418 self.expected_success(200, resp.status)419 return self._parse_resp(metadata)420 def set_metadata(self, share_id, metadata=None):421 return self._update_metadata(share_id, metadata)422 def update_all_metadata(self, share_id, metadata=None):423 return self._update_metadata(share_id, metadata, method="put")424 def delete_metadata(self, share_id, key):425 resp, body = self.delete("shares/%s/metadata/%s" % (share_id, key))426 self.expected_success(200, resp.status)427 return body428 def get_metadata(self, share_id):429 resp, body = self.get("shares/%s/metadata" % share_id)430 self.expected_success(200, resp.status)431 return self._parse_resp(body)432###############433 def create_security_service(self, ss_type="ldap", **kwargs):434 # ss_type: ldap, kerberos, active_directory435 # kwargs: name, description, dns_ip, server, domain, user, password436 post_body = {"type": ss_type}437 post_body.update(kwargs)438 body = json.dumps({"security_service": post_body})439 resp, body = self.post("security-services", body)440 self.expected_success(200, resp.status)441 return self._parse_resp(body)442 def update_security_service(self, ss_id, **kwargs):443 # ss_id - id of security-service entity444 # kwargs: dns_ip, server, domain, user, password, name, description445 # for 'active' status can be changed446 # only 'name' and 'description' fields447 body = json.dumps({"security_service": kwargs})448 resp, body = self.put("security-services/%s" % ss_id, body)449 self.expected_success(200, resp.status)450 return self._parse_resp(body)451 def get_security_service(self, ss_id):452 resp, body = self.get("security-services/%s" % ss_id)453 self.expected_success(200, resp.status)454 return self._parse_resp(body)455 def list_security_services(self, detailed=False, params=None):456 uri = "security-services"457 if detailed:458 uri += '/detail'459 if params:460 uri += "?%s" % urlparse.urlencode(params)461 resp, body = self.get(uri)462 self.expected_success(200, resp.status)463 return self._parse_resp(body)464 def delete_security_service(self, ss_id):465 resp, body = self.delete("security-services/%s" % ss_id)466 self.expected_success(202, resp.status)467 return body468###############469 def create_share_network(self, **kwargs):470 # kwargs: name, description471 # + for neutron: neutron_net_id, neutron_subnet_id472 body = json.dumps({"share_network": kwargs})473 resp, body = self.post("share-networks", body)474 self.expected_success(200, resp.status)475 return self._parse_resp(body)476 def update_share_network(self, sn_id, **kwargs):477 # kwargs: name, description478 # + for neutron: neutron_net_id, neutron_subnet_id479 body = json.dumps({"share_network": kwargs})480 resp, body = self.put("share-networks/%s" % sn_id, body)481 self.expected_success(200, resp.status)482 return self._parse_resp(body)483 def get_share_network(self, sn_id):484 resp, body = self.get("share-networks/%s" % sn_id)485 self.expected_success(200, resp.status)486 return self._parse_resp(body)487 def list_share_networks(self):488 resp, body = self.get("share-networks")489 self.expected_success(200, resp.status)490 return self._parse_resp(body)491 def list_share_networks_with_detail(self, params=None):492 """List the details of all shares."""493 uri = "share-networks/detail"494 if params:495 uri += "?%s" % urlparse.urlencode(params)496 resp, body = self.get(uri)497 self.expected_success(200, resp.status)498 return self._parse_resp(body)499 def delete_share_network(self, sn_id):500 resp, body = self.delete("share-networks/%s" % sn_id)501 self.expected_success(202, resp.status)502 return body503###############504 def _map_security_service_and_share_network(self, sn_id, ss_id,505 action="add"):506 # sn_id: id of share_network_entity507 # ss_id: id of security service entity508 # action: add, remove509 data = {510 "%s_security_service" % action: {511 "security_service_id": ss_id,512 }513 }514 body = json.dumps(data)515 resp, body = self.post("share-networks/%s/action" % sn_id, body)516 self.expected_success(200, resp.status)517 return self._parse_resp(body)518 def add_sec_service_to_share_network(self, sn_id, ss_id):519 body = self._map_security_service_and_share_network(sn_id, ss_id)520 return body521 def remove_sec_service_from_share_network(self, sn_id, ss_id):522 body = self._map_security_service_and_share_network(523 sn_id, ss_id, "remove")524 return body525 def list_sec_services_for_share_network(self, sn_id):526 resp, body = self.get("security-services?share_network_id=%s" % sn_id)527 self.expected_success(200, resp.status)528 return self._parse_resp(body)529###############530 def list_share_types(self, params=None):531 uri = 'types'532 if params is not None:533 uri += '?%s' % urlparse.urlencode(params)534 resp, body = self.get(uri)535 self.expected_success(200, resp.status)536 return self._parse_resp(body)537 def create_share_type(self, name, is_public=True, **kwargs):538 post_body = {539 'name': name,540 'extra_specs': kwargs.get('extra_specs'),541 'os-share-type-access:is_public': is_public,542 }543 post_body = json.dumps({'share_type': post_body})544 resp, body = self.post('types', post_body)545 self.expected_success(200, resp.status)546 return self._parse_resp(body)547 def delete_share_type(self, share_type_id):548 resp, body = self.delete("types/%s" % share_type_id)549 self.expected_success(202, resp.status)550 return body551 def get_share_type(self, share_type_id):552 resp, body = self.get("types/%s" % share_type_id)553 self.expected_success(200, resp.status)554 return self._parse_resp(body)555 def add_access_to_share_type(self, share_type_id, project_id):556 uri = 'types/%s/action' % share_type_id557 post_body = {'project': project_id}558 post_body = json.dumps({'addProjectAccess': post_body})559 resp, body = self.post(uri, post_body)560 self.expected_success(202, resp.status)561 return body562 def remove_access_from_share_type(self, share_type_id, project_id):563 uri = 'types/%s/action' % share_type_id564 post_body = {'project': project_id}565 post_body = json.dumps({'removeProjectAccess': post_body})566 resp, body = self.post(uri, post_body)567 self.expected_success(202, resp.status)568 return body569 def list_access_to_share_type(self, share_type_id):570 uri = 'types/%s/os-share-type-access' % share_type_id571 resp, body = self.get(uri)572 # [{"share_type_id": "%st_id%", "project_id": "%project_id%"}, ]573 self.expected_success(200, resp.status)574 return self._parse_resp(body)575###############576 def create_share_type_extra_specs(self, share_type_id, extra_specs):577 url = "types/%s/extra_specs" % share_type_id578 post_body = json.dumps({'extra_specs': extra_specs})579 resp, body = self.post(url, post_body)580 self.expected_success(200, resp.status)581 return self._parse_resp(body)582 def get_share_type_extra_spec(self, share_type_id, extra_spec_name):583 uri = "types/%s/extra_specs/%s" % (share_type_id, extra_spec_name)584 resp, body = self.get(uri)585 self.expected_success(200, resp.status)586 return self._parse_resp(body)587 def get_share_type_extra_specs(self, share_type_id, params=None):588 uri = "types/%s/extra_specs" % share_type_id589 if params is not None:590 uri += '?%s' % urlparse.urlencode(params)591 resp, body = self.get(uri)592 self.expected_success(200, resp.status)593 return self._parse_resp(body)594 def update_share_type_extra_spec(self, share_type_id, spec_name,595 spec_value):596 uri = "types/%s/extra_specs/%s" % (share_type_id, spec_name)597 extra_spec = {spec_name: spec_value}598 post_body = json.dumps(extra_spec)599 resp, body = self.put(uri, post_body)600 self.expected_success(200, resp.status)601 return self._parse_resp(body)602 def update_share_type_extra_specs(self, share_type_id, extra_specs):603 uri = "types/%s/extra_specs" % share_type_id604 extra_specs = {"extra_specs": extra_specs}605 post_body = json.dumps(extra_specs)606 resp, body = self.post(uri, post_body)607 self.expected_success(200, resp.status)608 return self._parse_resp(body)609 def delete_share_type_extra_spec(self, share_type_id, extra_spec_name):610 uri = "types/%s/extra_specs/%s" % (share_type_id, extra_spec_name)611 resp, body = self.delete(uri)612 self.expected_success(202, resp.status)613 return body614###############615 def list_share_servers(self, search_opts=None):616 """Get list of share servers."""617 uri = "share-servers"618 if search_opts:619 uri += "?%s" % urlparse.urlencode(search_opts)620 resp, body = self.get(uri)621 self.expected_success(200, resp.status)622 return self._parse_resp(body)623 def delete_share_server(self, share_server_id):624 """Delete share server by its ID."""625 uri = "share-servers/%s" % share_server_id626 resp, body = self.delete(uri)627 self.expected_success(202, resp.status)628 return body629 def show_share_server(self, share_server_id):630 """Get share server info."""631 uri = "share-servers/%s" % share_server_id632 resp, body = self.get(uri)633 self.expected_success(200, resp.status)634 return self._parse_resp(body)635 def show_share_server_details(self, share_server_id):636 """Get share server details only."""637 uri = "share-servers/%s/details" % share_server_id638 resp, body = self.get(uri)639 self.expected_success(200, resp.status)640 return self._parse_resp(body)641###############642 def list_pools(self, detail=False, search_opts=None):643 """Get list of scheduler pools."""644 uri = 'scheduler-stats/pools'645 if detail:646 uri += '/detail'647 if search_opts:648 uri += "?%s" % urlparse.urlencode(search_opts)649 resp, body = self.get(uri)650 self.expected_success(200, resp.status)651 return json.loads(body)652###############653 def list_availability_zones(self):654 """Get list of availability zones."""655 uri = 'os-availability-zone'656 resp, body = self.get(uri)657 self.expected_success(200, resp.status)...
identity_client.py
Source:identity_client.py
...34 'password': password35 }36 post_body = json.dumps({'user': post_body})37 resp, body = self.post('users', post_body)38 self.expected_success(201, resp.status)39 body = json.loads(body)40 return service_client.ResponseBody(resp, body['user'])41 def update_user(self, user_id, name, **kwargs):42 """Updates a user."""43 body = self.get_user(user_id)44 email = kwargs.get('email', body['email'])45 en = kwargs.get('enabled', body['enabled'])46 project_id = kwargs.get('project_id', body['project_id'])47 if 'default_project_id' in body.keys():48 default_project_id = kwargs.get('default_project_id',49 body['default_project_id'])50 else:51 default_project_id = kwargs.get('default_project_id')52 description = kwargs.get('description', body['description'])53 domain_id = kwargs.get('domain_id', body['domain_id'])54 post_body = {55 'name': name,56 'email': email,57 'enabled': en,58 'project_id': project_id,59 'default_project_id': default_project_id,60 'id': user_id,61 'domain_id': domain_id,62 'description': description63 }64 post_body = json.dumps({'user': post_body})65 resp, body = self.patch('users/%s' % user_id, post_body)66 self.expected_success(200, resp.status)67 body = json.loads(body)68 return service_client.ResponseBody(resp, body['user'])69 def update_user_password(self, user_id, password, original_password):70 """Updates a user password."""71 update_user = {72 'password': password,73 'original_password': original_password74 }75 update_user = json.dumps({'user': update_user})76 resp, _ = self.post('users/%s/password' % user_id, update_user)77 self.expected_success(204, resp.status)78 return service_client.ResponseBody(resp)79 def list_user_projects(self, user_id):80 """Lists the projects on which a user has roles assigned."""81 resp, body = self.get('users/%s/projects' % user_id)82 self.expected_success(200, resp.status)83 body = json.loads(body)84 return service_client.ResponseBodyList(resp, body['projects'])85 def get_users(self, params=None):86 """Get the list of users."""87 url = 'users'88 if params:89 url += '?%s' % parse.urlencode(params)90 resp, body = self.get(url)91 self.expected_success(200, resp.status)92 body = json.loads(body)93 return service_client.ResponseBodyList(resp, body['users'])94 def get_user(self, user_id):95 """GET a user."""96 resp, body = self.get("users/%s" % user_id)97 self.expected_success(200, resp.status)98 body = json.loads(body)99 return service_client.ResponseBody(resp, body['user'])100 def delete_user(self, user_id):101 """Deletes a User."""102 resp, body = self.delete("users/%s" % user_id)103 self.expected_success(204, resp.status)104 return service_client.ResponseBody(resp, body)105 def create_project(self, name, **kwargs):106 """Creates a project."""107 description = kwargs.get('description', None)108 en = kwargs.get('enabled', True)109 domain_id = kwargs.get('domain_id', 'default')110 post_body = {111 'description': description,112 'domain_id': domain_id,113 'enabled': en,114 'name': name115 }116 post_body = json.dumps({'project': post_body})117 resp, body = self.post('projects', post_body)118 self.expected_success(201, resp.status)119 body = json.loads(body)120 return service_client.ResponseBody(resp, body['project'])121 def list_projects(self, params=None):122 url = "projects"123 if params:124 url += '?%s' % parse.urlencode(params)125 resp, body = self.get(url)126 self.expected_success(200, resp.status)127 body = json.loads(body)128 return service_client.ResponseBodyList(resp, body['projects'])129 def update_project(self, project_id, **kwargs):130 body = self.get_project(project_id)131 name = kwargs.get('name', body['name'])132 desc = kwargs.get('description', body['description'])133 en = kwargs.get('enabled', body['enabled'])134 domain_id = kwargs.get('domain_id', body['domain_id'])135 post_body = {136 'id': project_id,137 'name': name,138 'description': desc,139 'enabled': en,140 'domain_id': domain_id,141 }142 post_body = json.dumps({'project': post_body})143 resp, body = self.patch('projects/%s' % project_id, post_body)144 self.expected_success(200, resp.status)145 body = json.loads(body)146 return service_client.ResponseBody(resp, body['project'])147 def get_project(self, project_id):148 """GET a Project."""149 resp, body = self.get("projects/%s" % project_id)150 self.expected_success(200, resp.status)151 body = json.loads(body)152 return service_client.ResponseBody(resp, body['project'])153 def delete_project(self, project_id):154 """Delete a project."""155 resp, body = self.delete('projects/%s' % str(project_id))156 self.expected_success(204, resp.status)157 return service_client.ResponseBody(resp, body)158 def create_role(self, name):159 """Create a Role."""160 post_body = {161 'name': name162 }163 post_body = json.dumps({'role': post_body})164 resp, body = self.post('roles', post_body)165 self.expected_success(201, resp.status)166 body = json.loads(body)167 return service_client.ResponseBody(resp, body['role'])168 def get_role(self, role_id):169 """GET a Role."""170 resp, body = self.get('roles/%s' % str(role_id))171 self.expected_success(200, resp.status)172 body = json.loads(body)173 return service_client.ResponseBody(resp, body['role'])174 def list_roles(self):175 """Get the list of Roles."""176 resp, body = self.get("roles")177 self.expected_success(200, resp.status)178 body = json.loads(body)179 return service_client.ResponseBodyList(resp, body['roles'])180 def update_role(self, name, role_id):181 """Create a Role."""182 post_body = {183 'name': name184 }185 post_body = json.dumps({'role': post_body})186 resp, body = self.patch('roles/%s' % str(role_id), post_body)187 self.expected_success(200, resp.status)188 body = json.loads(body)189 return service_client.ResponseBody(resp, body['role'])190 def delete_role(self, role_id):191 """Delete a role."""192 resp, body = self.delete('roles/%s' % str(role_id))193 self.expected_success(204, resp.status)194 return service_client.ResponseBody(resp, body)195 def assign_user_role(self, project_id, user_id, role_id):196 """Add roles to a user on a project."""197 resp, body = self.put('projects/%s/users/%s/roles/%s' %198 (project_id, user_id, role_id), None)199 self.expected_success(204, resp.status)200 return service_client.ResponseBody(resp, body)201 def create_domain(self, name, **kwargs):202 """Creates a domain."""203 description = kwargs.get('description', None)204 en = kwargs.get('enabled', True)205 post_body = {206 'description': description,207 'enabled': en,208 'name': name209 }210 post_body = json.dumps({'domain': post_body})211 resp, body = self.post('domains', post_body)212 self.expected_success(201, resp.status)213 body = json.loads(body)214 return service_client.ResponseBody(resp, body['domain'])215 def delete_domain(self, domain_id):216 """Delete a domain."""217 resp, body = self.delete('domains/%s' % str(domain_id))218 self.expected_success(204, resp.status)219 return service_client.ResponseBody(resp, body)220 def list_domains(self):221 """List Domains."""222 resp, body = self.get('domains')223 self.expected_success(200, resp.status)224 body = json.loads(body)225 return service_client.ResponseBodyList(resp, body['domains'])226 def update_domain(self, domain_id, **kwargs):227 """Updates a domain."""228 body = self.get_domain(domain_id)229 description = kwargs.get('description', body['description'])230 en = kwargs.get('enabled', body['enabled'])231 name = kwargs.get('name', body['name'])232 post_body = {233 'description': description,234 'enabled': en,235 'name': name236 }237 post_body = json.dumps({'domain': post_body})238 resp, body = self.patch('domains/%s' % domain_id, post_body)239 self.expected_success(200, resp.status)240 body = json.loads(body)241 return service_client.ResponseBody(resp, body['domain'])242 def get_domain(self, domain_id):243 """Get Domain details."""244 resp, body = self.get('domains/%s' % domain_id)245 self.expected_success(200, resp.status)246 body = json.loads(body)247 return service_client.ResponseBody(resp, body['domain'])248 def get_token(self, resp_token):249 """Get token details."""250 headers = {'X-Subject-Token': resp_token}251 resp, body = self.get("auth/tokens", headers=headers)252 self.expected_success(200, resp.status)253 body = json.loads(body)254 return service_client.ResponseBody(resp, body['token'])255 def delete_token(self, resp_token):256 """Deletes token."""257 headers = {'X-Subject-Token': resp_token}258 resp, body = self.delete("auth/tokens", headers=headers)259 self.expected_success(204, resp.status)260 return service_client.ResponseBody(resp, body)261 def create_group(self, name, **kwargs):262 """Creates a group."""263 description = kwargs.get('description', None)264 domain_id = kwargs.get('domain_id', 'default')265 project_id = kwargs.get('project_id', None)266 post_body = {267 'description': description,268 'domain_id': domain_id,269 'project_id': project_id,270 'name': name271 }272 post_body = json.dumps({'group': post_body})273 resp, body = self.post('groups', post_body)274 self.expected_success(201, resp.status)275 body = json.loads(body)276 return service_client.ResponseBody(resp, body['group'])277 def get_group(self, group_id):278 """Get group details."""279 resp, body = self.get('groups/%s' % group_id)280 self.expected_success(200, resp.status)281 body = json.loads(body)282 return service_client.ResponseBody(resp, body['group'])283 def list_groups(self):284 """Lists the groups."""285 resp, body = self.get('groups')286 self.expected_success(200, resp.status)287 body = json.loads(body)288 return service_client.ResponseBodyList(resp, body['groups'])289 def update_group(self, group_id, **kwargs):290 """Updates a group."""291 body = self.get_group(group_id)292 name = kwargs.get('name', body['name'])293 description = kwargs.get('description', body['description'])294 post_body = {295 'name': name,296 'description': description297 }298 post_body = json.dumps({'group': post_body})299 resp, body = self.patch('groups/%s' % group_id, post_body)300 self.expected_success(200, resp.status)301 body = json.loads(body)302 return service_client.ResponseBody(resp, body['group'])303 def delete_group(self, group_id):304 """Delete a group."""305 resp, body = self.delete('groups/%s' % str(group_id))306 self.expected_success(204, resp.status)307 return service_client.ResponseBody(resp, body)308 def add_group_user(self, group_id, user_id):309 """Add user into group."""310 resp, body = self.put('groups/%s/users/%s' % (group_id, user_id),311 None)312 self.expected_success(204, resp.status)313 return service_client.ResponseBody(resp, body)314 def list_group_users(self, group_id):315 """List users in group."""316 resp, body = self.get('groups/%s/users' % group_id)317 self.expected_success(200, resp.status)318 body = json.loads(body)319 return service_client.ResponseBodyList(resp, body['users'])320 def list_user_groups(self, user_id):321 """Lists groups which a user belongs to."""322 resp, body = self.get('users/%s/groups' % user_id)323 self.expected_success(200, resp.status)324 body = json.loads(body)325 return service_client.ResponseBodyList(resp, body['groups'])326 def delete_group_user(self, group_id, user_id):327 """Delete user in group."""328 resp, body = self.delete('groups/%s/users/%s' % (group_id, user_id))329 self.expected_success(204, resp.status)330 return service_client.ResponseBody(resp, body)331 def assign_user_role_on_project(self, project_id, user_id, role_id):332 """Add roles to a user on a project."""333 resp, body = self.put('projects/%s/users/%s/roles/%s' %334 (project_id, user_id, role_id), None)335 self.expected_success(204, resp.status)336 return service_client.ResponseBody(resp, body)337 def assign_user_role_on_domain(self, domain_id, user_id, role_id):338 """Add roles to a user on a domain."""339 resp, body = self.put('domains/%s/users/%s/roles/%s' %340 (domain_id, user_id, role_id), None)341 self.expected_success(204, resp.status)342 return service_client.ResponseBody(resp, body)343 def list_user_roles_on_project(self, project_id, user_id):344 """list roles of a user on a project."""345 resp, body = self.get('projects/%s/users/%s/roles' %346 (project_id, user_id))347 self.expected_success(200, resp.status)348 body = json.loads(body)349 return service_client.ResponseBodyList(resp, body['roles'])350 def list_user_roles_on_domain(self, domain_id, user_id):351 """list roles of a user on a domain."""352 resp, body = self.get('domains/%s/users/%s/roles' %353 (domain_id, user_id))354 self.expected_success(200, resp.status)355 body = json.loads(body)356 return service_client.ResponseBodyList(resp, body['roles'])357 def revoke_role_from_user_on_project(self, project_id, user_id, role_id):358 """Delete role of a user on a project."""359 resp, body = self.delete('projects/%s/users/%s/roles/%s' %360 (project_id, user_id, role_id))361 self.expected_success(204, resp.status)362 return service_client.ResponseBody(resp, body)363 def revoke_role_from_user_on_domain(self, domain_id, user_id, role_id):364 """Delete role of a user on a domain."""365 resp, body = self.delete('domains/%s/users/%s/roles/%s' %366 (domain_id, user_id, role_id))367 self.expected_success(204, resp.status)368 return service_client.ResponseBody(resp, body)369 def assign_group_role_on_project(self, project_id, group_id, role_id):370 """Add roles to a user on a project."""371 resp, body = self.put('projects/%s/groups/%s/roles/%s' %372 (project_id, group_id, role_id), None)373 self.expected_success(204, resp.status)374 return service_client.ResponseBody(resp, body)375 def assign_group_role_on_domain(self, domain_id, group_id, role_id):376 """Add roles to a user on a domain."""377 resp, body = self.put('domains/%s/groups/%s/roles/%s' %378 (domain_id, group_id, role_id), None)379 self.expected_success(204, resp.status)380 return service_client.ResponseBody(resp, body)381 def list_group_roles_on_project(self, project_id, group_id):382 """list roles of a user on a project."""383 resp, body = self.get('projects/%s/groups/%s/roles' %384 (project_id, group_id))385 self.expected_success(200, resp.status)386 body = json.loads(body)387 return service_client.ResponseBodyList(resp, body['roles'])388 def list_group_roles_on_domain(self, domain_id, group_id):389 """list roles of a user on a domain."""390 resp, body = self.get('domains/%s/groups/%s/roles' %391 (domain_id, group_id))392 self.expected_success(200, resp.status)393 body = json.loads(body)394 return service_client.ResponseBodyList(resp, body['roles'])395 def revoke_role_from_group_on_project(self, project_id, group_id, role_id):396 """Delete role of a user on a project."""397 resp, body = self.delete('projects/%s/groups/%s/roles/%s' %398 (project_id, group_id, role_id))399 self.expected_success(204, resp.status)400 return service_client.ResponseBody(resp, body)401 def revoke_role_from_group_on_domain(self, domain_id, group_id, role_id):402 """Delete role of a user on a domain."""403 resp, body = self.delete('domains/%s/groups/%s/roles/%s' %404 (domain_id, group_id, role_id))405 self.expected_success(204, resp.status)406 return service_client.ResponseBody(resp, body)407 def create_trust(self, trustor_user_id, trustee_user_id, project_id,408 role_names, impersonation, expires_at):409 """Creates a trust."""410 roles = [{'name': n} for n in role_names]411 post_body = {412 'trustor_user_id': trustor_user_id,413 'trustee_user_id': trustee_user_id,414 'project_id': project_id,415 'impersonation': impersonation,416 'roles': roles,417 'expires_at': expires_at418 }419 post_body = json.dumps({'trust': post_body})420 resp, body = self.post('OS-TRUST/trusts', post_body)421 self.expected_success(201, resp.status)422 body = json.loads(body)423 return service_client.ResponseBody(resp, body['trust'])424 def delete_trust(self, trust_id):425 """Deletes a trust."""426 resp, body = self.delete("OS-TRUST/trusts/%s" % trust_id)427 self.expected_success(204, resp.status)428 return service_client.ResponseBody(resp, body)429 def get_trusts(self, trustor_user_id=None, trustee_user_id=None):430 """GET trusts."""431 if trustor_user_id:432 resp, body = self.get("OS-TRUST/trusts?trustor_user_id=%s"433 % trustor_user_id)434 elif trustee_user_id:435 resp, body = self.get("OS-TRUST/trusts?trustee_user_id=%s"436 % trustee_user_id)437 else:438 resp, body = self.get("OS-TRUST/trusts")439 self.expected_success(200, resp.status)440 body = json.loads(body)441 return service_client.ResponseBodyList(resp, body['trusts'])442 def get_trust(self, trust_id):443 """GET trust."""444 resp, body = self.get("OS-TRUST/trusts/%s" % trust_id)445 self.expected_success(200, resp.status)446 body = json.loads(body)447 return service_client.ResponseBody(resp, body['trust'])448 def get_trust_roles(self, trust_id):449 """GET roles delegated by a trust."""450 resp, body = self.get("OS-TRUST/trusts/%s/roles" % trust_id)451 self.expected_success(200, resp.status)452 body = json.loads(body)453 return service_client.ResponseBodyList(resp, body['roles'])454 def get_trust_role(self, trust_id, role_id):455 """GET role delegated by a trust."""456 resp, body = self.get("OS-TRUST/trusts/%s/roles/%s"457 % (trust_id, role_id))458 self.expected_success(200, resp.status)459 body = json.loads(body)460 return service_client.ResponseBody(resp, body['role'])461 def check_trust_role(self, trust_id, role_id):462 """HEAD Check if role is delegated by a trust."""463 resp, body = self.head("OS-TRUST/trusts/%s/roles/%s"464 % (trust_id, role_id))465 self.expected_success(200, resp.status)...
rebaselineserver_unittest.py
Source:rebaselineserver_unittest.py
1# Copyright (C) 2010 Google Inc. All rights reserved.2#3# Redistribution and use in source and binary forms, with or without4# modification, are permitted provided that the following conditions are5# met:6#7# * Redistributions of source code must retain the above copyright8# notice, this list of conditions and the following disclaimer.9# * Redistributions in binary form must reproduce the above10# copyright notice, this list of conditions and the following disclaimer11# in the documentation and/or other materials provided with the12# distribution.13# * Neither the name of Google Inc. nor the names of its14# contributors may be used to endorse or promote products derived from15# this software without specific prior written permission.16#17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28import unittest29from webkitpy.common.system import filesystem_mock30from webkitpy.layout_tests.port import base31from webkitpy.layout_tests.port.webkit import WebKitPort32from webkitpy.tool.commands import rebaselineserver33from webkitpy.tool.mocktool import MockSCM34class RebaselineTestTest(unittest.TestCase):35 def test_text_rebaseline_update(self):36 self._assertRebaseline(37 test_files=(38 'fast/text-expected.txt',39 'platform/mac/fast/text-expected.txt',40 ),41 results_files=(42 'fast/text-actual.txt',43 ),44 test_name='fast/text.html',45 baseline_target='mac',46 baseline_move_to='none',47 expected_success=True,48 expected_log=[49 'Rebaselining fast/text...',50 ' Updating baselines for mac',51 ' Updated text-expected.txt',52 ])53 def test_text_rebaseline_new(self):54 self._assertRebaseline(55 test_files=(56 'fast/text-expected.txt',57 ),58 results_files=(59 'fast/text-actual.txt',60 ),61 test_name='fast/text.html',62 baseline_target='mac',63 baseline_move_to='none',64 expected_success=True,65 expected_log=[66 'Rebaselining fast/text...',67 ' Updating baselines for mac',68 ' Updated text-expected.txt',69 ])70 def test_text_rebaseline_move_no_op_1(self):71 self._assertRebaseline(72 test_files=(73 'fast/text-expected.txt',74 'platform/win/fast/text-expected.txt',75 ),76 results_files=(77 'fast/text-actual.txt',78 ),79 test_name='fast/text.html',80 baseline_target='mac',81 baseline_move_to='mac-leopard',82 expected_success=True,83 expected_log=[84 'Rebaselining fast/text...',85 ' Updating baselines for mac',86 ' Updated text-expected.txt',87 ])88 def test_text_rebaseline_move_no_op_2(self):89 self._assertRebaseline(90 test_files=(91 'fast/text-expected.txt',92 'platform/mac/fast/text-expected.checksum',93 ),94 results_files=(95 'fast/text-actual.txt',96 ),97 test_name='fast/text.html',98 baseline_target='mac',99 baseline_move_to='mac-leopard',100 expected_success=True,101 expected_log=[102 'Rebaselining fast/text...',103 ' Moving current mac baselines to mac-leopard',104 ' No current baselines to move',105 ' Updating baselines for mac',106 ' Updated text-expected.txt',107 ])108 def test_text_rebaseline_move(self):109 self._assertRebaseline(110 test_files=(111 'fast/text-expected.txt',112 'platform/mac/fast/text-expected.txt',113 ),114 results_files=(115 'fast/text-actual.txt',116 ),117 test_name='fast/text.html',118 baseline_target='mac',119 baseline_move_to='mac-leopard',120 expected_success=True,121 expected_log=[122 'Rebaselining fast/text...',123 ' Moving current mac baselines to mac-leopard',124 ' Moved text-expected.txt',125 ' Updating baselines for mac',126 ' Updated text-expected.txt',127 ])128 def test_text_rebaseline_move_only_images(self):129 self._assertRebaseline(130 test_files=(131 'fast/image-expected.txt',132 'platform/mac/fast/image-expected.txt',133 'platform/mac/fast/image-expected.png',134 'platform/mac/fast/image-expected.checksum',135 ),136 results_files=(137 'fast/image-actual.png',138 'fast/image-actual.checksum',139 ),140 test_name='fast/image.html',141 baseline_target='mac',142 baseline_move_to='mac-leopard',143 expected_success=True,144 expected_log=[145 'Rebaselining fast/image...',146 ' Moving current mac baselines to mac-leopard',147 ' Moved image-expected.checksum',148 ' Moved image-expected.png',149 ' Updating baselines for mac',150 ' Updated image-expected.checksum',151 ' Updated image-expected.png',152 ])153 def test_text_rebaseline_move_already_exist(self):154 self._assertRebaseline(155 test_files=(156 'fast/text-expected.txt',157 'platform/mac-leopard/fast/text-expected.txt',158 'platform/mac/fast/text-expected.txt',159 ),160 results_files=(161 'fast/text-actual.txt',162 ),163 test_name='fast/text.html',164 baseline_target='mac',165 baseline_move_to='mac-leopard',166 expected_success=False,167 expected_log=[168 'Rebaselining fast/text...',169 ' Moving current mac baselines to mac-leopard',170 ' Already had baselines in mac-leopard, could not move existing mac ones',171 ])172 def test_image_rebaseline(self):173 self._assertRebaseline(174 test_files=(175 'fast/image-expected.txt',176 'platform/mac/fast/image-expected.png',177 'platform/mac/fast/image-expected.checksum',178 ),179 results_files=(180 'fast/image-actual.png',181 'fast/image-actual.checksum',182 ),183 test_name='fast/image.html',184 baseline_target='mac',185 baseline_move_to='none',186 expected_success=True,187 expected_log=[188 'Rebaselining fast/image...',189 ' Updating baselines for mac',190 ' Updated image-expected.checksum',191 ' Updated image-expected.png',192 ])193 def _assertRebaseline(self, test_files, results_files, test_name, baseline_target, baseline_move_to, expected_success, expected_log):194 log = []195 test_config = get_test_config(test_files, results_files)196 success = rebaselineserver._rebaseline_test(197 test_name,198 baseline_target,199 baseline_move_to,200 test_config,201 log=lambda l: log.append(l))202 self.assertEqual(expected_log, log)203 self.assertEqual(expected_success, success)204class GetActualResultFilesTest(unittest.TestCase):205 def test(self):206 test_config = get_test_config(result_files=(207 'fast/text-actual.txt',208 'fast2/text-actual.txt',209 'fast/text2-actual.txt',210 'fast/text-notactual.txt',211 ))212 self.assertEqual(213 ('text-actual.txt',),214 rebaselineserver._get_actual_result_files(215 'fast/text.html', test_config))216class GetBaselinesTest(unittest.TestCase):217 def test_no_baselines(self):218 self._assertBaselines(219 test_files=(),220 test_name='fast/missing.html',221 expected_baselines={})222 def test_text_baselines(self):223 self._assertBaselines(224 test_files=(225 'fast/text-expected.txt',226 'platform/mac/fast/text-expected.txt',227 ),228 test_name='fast/text.html',229 expected_baselines={230 'mac': {'.txt': True},231 'base': {'.txt': False},232 })233 def test_image_and_text_baselines(self):234 self._assertBaselines(235 test_files=(236 'fast/image-expected.txt',237 'platform/mac/fast/image-expected.png',238 'platform/mac/fast/image-expected.checksum',239 'platform/win/fast/image-expected.png',240 'platform/win/fast/image-expected.checksum',241 ),242 test_name='fast/image.html',243 expected_baselines={244 'base': {'.txt': True},245 'mac': {'.checksum': True, '.png': True},246 'win': {'.checksum': False, '.png': False},247 })248 def test_extra_baselines(self):249 self._assertBaselines(250 test_files=(251 'fast/text-expected.txt',252 'platform/nosuchplatform/fast/text-expected.txt',253 ),254 test_name='fast/text.html',255 expected_baselines={'base': {'.txt': True}})256 def _assertBaselines(self, test_files, test_name, expected_baselines):257 actual_baselines = rebaselineserver._get_test_baselines(258 test_name, get_test_config(test_files))259 self.assertEqual(expected_baselines, actual_baselines)260def get_test_config(test_files=[], result_files=[]):261 layout_tests_directory = base.Port().layout_tests_dir()262 results_directory = '/WebKitBuild/Debug/layout-test-results'263 mock_filesystem = filesystem_mock.MockFileSystem()264 for file in test_files:265 file_path = mock_filesystem.join(layout_tests_directory, file)266 mock_filesystem.files[file_path] = ''267 for file in result_files:268 file_path = mock_filesystem.join(results_directory, file)269 mock_filesystem.files[file_path] = ''270 class TestMacPort(WebKitPort):271 def __init__(self):272 WebKitPort.__init__(self, filesystem=mock_filesystem)273 self._name = 'mac'274 return rebaselineserver.TestConfig(275 TestMacPort(),276 layout_tests_directory,277 results_directory,278 ('mac', 'mac-leopard', 'win', 'linux'),279 mock_filesystem,...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!