def add(self, items): """ Add an item or a list of items to the container """ # Convert to set representation if isinstance(items, list): items = set(items) else: items = set([items]) # If there are any new items add_items = items - self._items if add_items: log.info("Adding {0} to {1}'s {2}".format( listed([item.identifier for item in add_items], self._class.__name__, max=10), self._object.identifier, self.__class__.__name__)) self._items.update(items) if config.get_cache_level() != config.CACHE_NONE: self._modified = True else: self._update()
def _fetch(self, inject=None): """ Fetch user data from the server """ TCMS._fetch(self, inject) if inject is None: # Search by id if self._id is not TCMSNone: try: log.info("Fetching user " + self.identifier) inject = self._server.User.filter({"id": self.id})[0] except IndexError: raise TCMSError("Cannot find user for " + self.identifier) # Search by login elif self._login is not TCMSNone: try: log.info("Fetching user for login '{0}'".format( self.login)) inject = self._server.User.filter({"username": self.login})[0] except IndexError: raise TCMSError("No user found for login '{0}'".format( self.login)) # Search by email elif self._email is not TCMSNone: try: log.info("Fetching user for email '{0}'".format( self.email)) inject = self._server.User.filter({"email": self.email})[0] except IndexError: raise TCMSError("No user found for email '{0}'".format( self.email)) # Otherwise initialize to the current user else: log.info("Fetching the current user") inject = self._server.User.filter()[0] self._index("i-am-current-user") # Initialize data from the inject and index into cache log.debug("Initializing user UID#{0}".format(inject["id"])) log.data(pretty(inject)) self._inject = inject self._id = inject["id"] self._login = inject["username"] self._email = inject["email"] if inject["first_name"] and inject["last_name"]: self._name = inject["first_name"] + " " + inject["last_name"] else: self._name = None self._index(self.login, self.email)
def remove(self, items): """ Remove an item or a list of items from the container """ # Convert to set representation if isinstance(items, list): items = set(items) else: items = set([items]) # If there are any items to be removed remove_items = items.intersection(self._items) if remove_items: log.info("Removing {0} from {1}'s {2}".format( listed([item.identifier for item in remove_items], self._class.__name__, max=10), self._object.identifier, self.__class__.__name__)) self._items.difference_update(items) if config.get_cache_level() != config.CACHE_NONE: self._modified = True else: self._update()
def _update(self): """ Save test run data to the server """ # Prepare the update hash hash = {} hash["build"] = self.build.id hash["default_tester"] = self.tester.id hash["estimated_time"] = self.time hash["manager"] = self.manager.id hash["notes"] = self.notes # This is required until BZ#731982 is fixed hash["product"] = self.build.product.id hash["summary"] = self.summary # Update status field only if its value has changed. This is to avoid # updating the 'Finished at' field, which is done automatically by # TCMS even when "switching" from 'Finished' to 'Finished'. if self._status != self._old_status: self._old_status = self._status hash["status"] = self.status.id log.info("Updating test run " + self.identifier) log.data(pretty(hash)) self._server.TestRun.update(self.id, hash)
def _fetch(self, inject=None): """ Get the missing build data """ TCMS._fetch(self, inject) # Directly fetch from the initial object dict if inject is not None: log.info("Processing build ID#{0} inject".format( inject["build_id"])) # Search by build id elif self._id is not TCMSNone: try: log.info("Fetching build " + self.identifier) inject = self._server.Build.filter({'pk': self.id})[0] except IndexError as error: log.debug(error) raise TCMSError("Cannot find build for " + self.identifier) # Search by build name and product else: try: log.info("Fetching build '{0}' of '{1}'".format( self.name, self.product.name)) inject = self._server.Build.filter({ 'name': self.name, 'product': self.product.id })[0] self._id = inject["build_id"] except IndexError as error: log.debug(error) raise TCMSError("Build '{0}' not found in '{1}'".format( self.name, self.product.name)) except KeyError: if "args" in inject: log.debug(inject["args"]) raise TCMSError("Build '{0}' not found in '{1}'".format( self.name, self.product.name)) # Initialize data from the inject and index into cache log.debug("Initializing Build ID#{0}".format(inject["build_id"])) log.data(pretty(inject)) self._inject = inject self._id = inject["build_id"] self._name = inject["name"] self._product = Product({ "id": inject["product_id"], "name": inject["product"] }) self._index("{0}---in---{1}".format(self.name, self.product.name))
def _fetch(self, inject=None): """ Get the missing category data """ TCMS._fetch(self, inject) # Directly fetch from the initial object dict if inject is not None: log.info("Processing category ID#{0} inject".format(inject["id"])) # Search by category id elif self._id is not TCMSNone: try: log.info("Fetching category {0}".format(self.identifier)) inject = self._server.Product.get_category(self.id) except xmlrpc.client.Fault as error: log.debug(error) raise TCMSError("Cannot find category for " + self.identifier) # Search by category name and product else: try: log.info("Fetching category '{0}' of '{1}'".format( self.name, self.product.name)) inject = self._server.Product.check_category( self.name, self.product.id) except xmlrpc.client.Fault as error: log.debug(error) raise TCMSError("Category '{0}' not found in" " '{1}'".format(self.name, self.product.name)) # Initialize data from the inject and index into cache log.debug("Initializing category ID#{0}".format(inject["id"])) log.data(pretty(inject)) self._inject = inject self._id = inject["id"] self._name = inject["name"] self._product = Product({ "id": inject["product_id"], "name": inject["product"] }) self._index("{0}---in---{1}".format(self.name, self.product.name))
def _fetch(self, inject=None): """ Initialize / refresh test case data. Either fetch them from the server or use provided hash. """ TCMS._fetch(self, inject) # Fetch the data hash from the server unless provided if inject is None: log.info("Fetching test case " + self.identifier) try: inject = self._server.TestCase.filter({'pk': self.id})[0] except IndexError as error: log.debug(error) raise TCMSError( "Failed to fetch test case TC#{0}".format(self.id)) self._inject = inject else: self._id = inject["case_id"] log.debug("Initializing test case " + self.identifier) log.data(pretty(inject)) # Set up attributes self._arguments = inject["arguments"] self._author = User(inject["author_id"]) self._category = Category(inject["category_id"]) if isinstance(inject["create_date"], str): self._created = datetime.datetime.strptime( inject["create_date"], "%Y-%m-%d %H:%M:%S") else: self._created = inject["create_date"] self._link = inject["extra_link"] self._notes = inject["notes"] self._priority = Priority(inject["priority_id"]) self._requirement = inject["requirement"] self._script = inject["script"] self._status = CaseStatus(inject["case_status_id"]) self._summary = inject["summary"] self._time = inject["estimated_time"] if inject["default_tester_id"] is not None: self._tester = User(inject["default_tester_id"]) else: self._tester = None # Handle manual, automated and autoproposed self._automated = inject["is_automated"] in [1, '1', 2, '2'] self._manual = inject["is_automated"] in [0, '0', 2, '2'] self._autoproposed = inject["is_automated_proposed"] # Empty script or arguments to be handled same as None if self._script == "": self._script = None if self._arguments == "": self._arguments = None # Test case documentation for attribute in ["setup", "action", "effect", "breakdown"]: if "text" in inject: setattr(self, "_" + attribute, inject["text"][attribute]) else: setattr(self, "_" + attribute, None) # Initialize containers self._bugs = CaseBugs(self) self._testplans = CasePlans(self) self._components = CaseComponents(self) # If all tags are cached, initialize them directly from the inject if "tag" in inject and Tag._is_cached(inject["tag"]): self._tags = CaseTags( self, inset=[Tag(tag) for tag in inject["tag"]]) else: self._tags = CaseTags(self) # Index the fetched object into cache self._index()
def _create(self, summary, category, **kwargs): """ Create a new test case """ hash = {} # Summary hash["summary"] = summary # If category provided as text, we need product as well product = kwargs.get("product") if isinstance(category, str) and not kwargs.get("product"): raise TCMSError( "Need product when category specified by name") # Category & Product if isinstance(category, str): category = Category(category=category, product=product) elif not isinstance(category, Category): raise TCMSError("Invalid category '{0}'".format(category)) hash["category"] = category.id hash["product"] = category.product.id # Priority priority = kwargs.get("priority") if priority is None: priority = Priority("P3") elif not isinstance(priority, Priority): priority = Priority(priority) hash["priority"] = priority.id # User tester = kwargs.get("tester") if tester: if isinstance(tester, str): tester = User(login=tester) hash["default_tester"] = tester.login # Script, arguments, requirement & reference link hash["script"] = kwargs.get("script") hash["arguments"] = kwargs.get("arguments") hash["requirement"] = kwargs.get("requirement") hash["extra_link"] = kwargs.get("link") # Case Status status = kwargs.get("status") if status: if isinstance(status, str): status = CaseStatus(status) hash["case_status"] = status.id # Manual, automated and autoproposed automated = kwargs.get("automated", True) autoproposed = kwargs.get("autoproposed", False) manual = kwargs.get("manual", False) if automated and manual: hash["is_automated"] = 2 elif automated: hash["is_automated"] = 1 else: hash["is_automated"] = 0 hash["is_automated_proposed"] = autoproposed # Estimated time hash["estimated_time"] = kwargs.get("time", '00:00:00') # Notes notes = kwargs.get("notes") if notes: hash["notes"] = notes # Submit log.info("Creating a new test case") log.data(pretty(hash)) testcasehash = self._server.TestCase.create(hash) log.data(pretty(testcasehash)) try: self._id = testcasehash["case_id"] except TypeError: log.debug("Failed to create a new test case") log.data(pretty(hash)) log.data(pretty(testcasehash)) raise TCMSError("Failed to create test case") self._fetch(testcasehash) log.info("Successfully created {0}".format(self))
def _create(self, testplan, product=None, version=None, build=None, summary=None, notes=None, manager=None, tester=None, **kwargs): """ Create a new test run """ hash = {} # Test plan if isinstance(testplan, int): testplan = TestPlan(testplan) hash["plan"] = testplan.id # Product & version if product is None: product = testplan.product elif not isinstance(product, Product): product = Product(product) hash["product"] = product.id if version is None: version = testplan.version elif isinstance(version, int): version = Version(version) else: version = Version(name=version, product=product) hash["product_version"] = version.id # Build if build is None: build = "unspecified" if isinstance(build, str): build = Build(build=build, product=product) hash["build"] = build.id # Summary & notes if summary is None: summary = "{0} on {1}".format(testplan.name, build) if notes is None: notes = "" hash["summary"] = summary hash["notes"] = notes # Manager & tester (current user by default) if not isinstance(manager, User): manager = User(manager) if not isinstance(tester, User): tester = User(tester) hash["manager"] = manager.id hash["default_tester"] = tester.id # Submit to the server and initialize log.info("Creating a new test run based on {0}".format(testplan)) log.data(pretty(hash)) testrunhash = self._server.TestRun.create(hash) log.data(pretty(testrunhash)) try: self._id = testrunhash["run_id"] except TypeError: log.debug("Failed to create a new test run based on {0}".format( testplan)) log.data(pretty(hash)) log.data(pretty(testrunhash)) raise TCMSError("Failed to create test run") self._fetch(testrunhash) # Add newly created test run to testplan.testruns container if PlanRuns._is_cached(testplan.testruns): testplan.testruns._fetch(list(testplan.testruns) + [self]) log.info("Successfully created {0}".format(self))
def _remove(self, plans): """ Unlink provided plans from the test case """ for plan in plans: log.info("Unlinking {0} from {1}".format(plan.identifier, self._identifier)) self._server.TestPlan.remove_case(plan.id, self.id)
def _add(self, plans): """ Link provided plans to the test case """ for plan in plans: log.info("Linking {0} to {1}".format(plan.identifier, self._identifier)) self._server.TestPlan.add_case(plan.id, self.id)
def _remove(self, tags): """ Detach provided tags from the test case """ for tag in tags: log.info("Untagging {0} of {1}".format(self._identifier, tag.name)) self._server.TestCase.remove_tag(self.id, tag.name)
def _add(self, tags): """ Attach provided tags to the test case """ for tag in tags: log.info("Tagging {0} with {1}".format(self._identifier, tag.name)) self._server.TestCase.add_tag(self.id, tag.name)
def _remove(self, components): """ Unlink provided components from the test case """ for component in components: log.info("Unlinking {0} from {1}".format(component.name, self._identifier)) self._server.TestCase.remove_component(self.id, component.id)
def _fetch(self, inject=None): """ Initialize / refresh test plan data. Either fetch them from the server or use provided hash. """ TCMS._fetch(self, inject) # Fetch the data hash from the server unless provided if inject is None: log.info("Fetching test plan " + self.identifier) try: inject = self._server.TestPlan.filter({'pk': self.id})[0] except IndexError as error: log.debug(error) raise TCMSError("Failed to fetch test plan TP#{0}".format( self.id)) self._inject = inject # Otherwise just initialize the id from inject else: self._id = inject["plan_id"] log.debug("Initializing test plan " + self.identifier) log.data(pretty(inject)) if "plan_id" not in inject: log.data(pretty(inject)) raise TCMSError("Failed to initialize " + self.identifier) # Set up attributes self._author = User(inject["author_id"]) if inject["owner_id"] is not None: self._owner = User(inject["owner_id"]) else: self._owner = None self._name = inject["name"] self._product = Product({ "id": inject["product_id"], "name": inject["product"] }) self._version = Version({ "id": inject["product_version_id"], "value": inject["product_version"], "product_id": inject["product_id"] }) self._type = PlanType(inject["type_id"]) self._is_active = inject["is_active"] in ["True", True] if inject["parent_id"] is not None: self._parent = TestPlan(inject["parent_id"]) else: self._parent = None # Initialize containers self._testcases = PlanCases(self) self._testruns = PlanRuns(self) self._children = ChildPlans(self) # If all tags are cached, initialize them directly from the inject if "tag" in inject and Tag._is_cached(inject["tag"]): self._tags = PlanTags(self, inset=[Tag(tag) for tag in inject["tag"]]) else: self._tags = PlanTags(self) # Index the fetched object into cache self._index()