Skip to content

Commit

Permalink
Merge pull request #10 from netzulo/req_tprojects
Browse files Browse the repository at this point in the history
[qatl] fixing #7 'tl.getProjects'
  • Loading branch information
netzulo committed Dec 8, 2017
2 parents c6e2feb + a50d647 commit 21adff3
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 60 deletions.
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ qatestlink
:alt: GitHub release
:target: https://img.shields.io/github/release/netzulo/qatestlink.svg

+-----------------------+-----------------------------------------------------------------------+------------------------------------------------------------------------------------------------+
| Branch | Linux Deploy | Windows Deploy |
+=======================+=======================================================================+================================================================================================+
| master | .. image:: https://travis-ci.org/netzulo/qatestlink.svg?branch=master | .. image:: https://ci.appveyor.com/api/projects/status/7low4kw7qa6a5vem/branch/master?svg=true |
+-----------------------+-----------------------+-----------------------------------------------+------------------------------------------------------------------------------------------------+
+------------------------+-------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+
| Branch | Linux Deploy | Windows Deploy |
+========================+=========================================================================+==================================================================================================+
| master | .. image:: https://travis-ci.org/netzulo/qatestlink.svg?branch=master | .. image:: https://ci.appveyor.com/api/projects/status/7low4kw7qa6a5vem/branch/master?svg=true |
+------------------------+-------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------+


Python tested versions
Expand Down Expand Up @@ -93,6 +93,6 @@ Configuration File
Tests
-----

*Just execute on command line*
*You will need real testlink app running before you can just execute on command line*

``python setup.py test``
Empty file.
50 changes: 50 additions & 0 deletions qatestlink/core/models/tl_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
"""TODO: doc module"""


class ModelBase(object):
"""TODO: doc class"""

def __init__(self):
"""TODO: doc method"""
pass


class TProject(ModelBase):
"""TODO: doc class"""

_res_members = None

# Testlink object properties
id = None
name = None
is_public = None

def __init__(self, res_members):
"""TODO: doc method"""
super(TProject, self).__init__()
if res_members is None:
raise Exception('Bad param, res_member can\'t be None')
if len(res_members) <= 0:
raise Exception(
'Bad param, res_member can\'t be empty list')
self._res_members = res_members
self._load()

def _load(self):
for res_member in self._res_members:
name = res_member.name
value = res_member.value
if name == 'id':
self.id = value
if name == 'name':
self.name = value
if name == 'is_public':
self.is_public = value

def __repr__(self):
return "TProject: id={}, name={}, is_public={}".format(
self.id,
self.name,
self.is_public
)
105 changes: 70 additions & 35 deletions qatestlink/core/testlink_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
import json
import logging
import requests
from qatestlink.core.utils.logger_manager import LoggerManager
from qatestlink.core.connections.connection_base import ConnectionBase
from qatestlink.core.utils.Utils import read_file
from qatestlink.core.xmls.route_type import RouteType
from qatestlink.core.xmls.request_handler import RequestHandler
from qatestlink.core.xmls.response_handler import ResponseHandler
from qatestlink.core.xmls.base_handler import BaseHandler
from qatestlink.core.models.tl_models import TProject


PATH_CONFIG = 'qatestlink/configs/settings.json'
Expand Down Expand Up @@ -70,7 +73,25 @@ def api_login(self, dev_key=None):
dev_key = self._settings.get('dev_key')
req_data = self._xml_manager.req_check_dev_key(dev_key)
res = self._conn.post(self._xml_manager.headers, req_data)
self._xml_manager.res_check_dev_key(res.status_code, res.text)
res_xml = self._xml_manager.res_check_dev_key(
res.status_code, res.text)
node_boolean = self._xml_manager.handler.find_node(
'boolean', xml_str=res_xml)
if node_boolean is None:
return False
return bool(node_boolean.text)

def api_get_tprojects(self, dev_key=None):
"""Call to method naed ''"""
if dev_key is None:
dev_key = self._settings.get('dev_key')
req_data = self._xml_manager.req_get_tprojects(dev_key)
res = self._conn.post(self._xml_manager.headers, req_data)
res_as_models = self._xml_manager.res_get_tprojects(
res.status_code, res.text, as_models=True)
# TODO: filter by name and/or value
return res_as_models


class XMLRPCManager(object):
"""
Expand All @@ -85,13 +106,15 @@ class XMLRPCManager(object):

log = None
headers = None
handler = None

def __init__(self, log):
self.log = log
self._request_handler = RequestHandler(self.log)
self._response_handler = ResponseHandler(self.log)
self._error_handler = None
self.headers = {'Content-Type': 'application/xml'}
self.handler = BaseHandler(self.log)

def req_check_dev_key(self, dev_key):
"""
Expand All @@ -113,43 +136,55 @@ def res_check_dev_key(self, status_code, res_str):
raise Exception(
"status_code invalid: code={}".format(
status_code))
res = self._response_handler.create(
RouteType.TLINK_CHECK_DEV_KEY,
res_str)
self.log.info("XML response for: {}".format(
RouteType.TLINK_CHECK_DEV_KEY.value))
return res
return self._response_handler.create(
RouteType.TLINK_CHECK_DEV_KEY, res_str)

def req_get_tprojects(self, dev_key):
"""
Obtains all test projects created on remote
testlink database, can filter with any property+value
combination
:return:
List of TProject objects containing all database
data loaded
"""
req = self._request_handler.create(
RouteType.TPROJECTS)
return self._request_handler.add_param(
req, 'struct', 'devKey', dev_key)

def res_get_tprojects(self, status_code, res_str, as_models=True):
"""
Parse and validate response for method
named 'tl.getProjects', by default response list
of TProject objects, can response xml string too
:return:
if as_models is True
list of objects instanced with
Model classes
if as_models is False
string xml object ready to
parse/write/find/add Elements on it
"""
if status_code != 200:
raise Exception(
"status_code invalid: code={}".format(
status_code))
res = self._response_handler.create(
RouteType.TPROJECTS, res_str)
if not as_models:
return res
# TODO: create objects and return them as list
res_members_list = self._response_handler.get_response_members(
xml_str=res)
# TODO: build objects
tprojects = list()
for res_members in res_members_list:
#TODO: all members by project
tproject = TProject(res_members)
tprojects.append(tproject)
return tprojects

class LoggerManager(object):
"""
Start logger named 'qatestlink'
with DEBUG level and just with console reporting
"""

log = None

def __init__(self, log_level=None):
"""Start logger"""
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('qatestlink')
logger_stream = logging.StreamHandler()
if log_level is None or log_level == 'DEBUG':
log_level = logging.DEBUG
elif log_level == 'INFO':
log_level = logging.INFO
elif log_level == 'WARNING':
log_level = logging.WARNING
elif log_level == 'ERROR':
log_level = logging.ERROR
elif log_level == 'CRITICAL':
log_level = logging.CRITICAL
logger.setLevel(log_level)
logger_stream.setLevel(log_level)
logger_stream.setFormatter(formatter)
logger.addHandler(logger_stream)
# alias to improve logging calls
self.log = logger

36 changes: 36 additions & 0 deletions qatestlink/core/utils/logger_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""TODO: doc module"""


import logging


class LoggerManager(object):
"""
Start logger named 'qatestlink'
with DEBUG level and just with console reporting
"""

log = None

def __init__(self, log_level=None):
"""Start logger"""
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('qatestlink')
logger_stream = logging.StreamHandler()
if log_level is None or log_level == 'DEBUG':
log_level = logging.DEBUG
elif log_level == 'INFO':
log_level = logging.INFO
elif log_level == 'WARNING':
log_level = logging.WARNING
elif log_level == 'ERROR':
log_level = logging.ERROR
elif log_level == 'CRITICAL':
log_level = logging.CRITICAL
logger.setLevel(log_level)
logger_stream.setLevel(log_level)
logger_stream.setFormatter(formatter)
logger.addHandler(logger_stream)
# alias to improve logging calls
self.log = logger
49 changes: 44 additions & 5 deletions qatestlink/core/xmls/base_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,65 @@ def create_node(self, tag, parent=None, text=None):
MSG_ADDED_TEXT.format(tag, text))
return node

def find_node(self, tag, req_str=None, parent=None):
def find_node(self, tag, xml_str=None, parent=None):
"""
Returns firt node obtained iter
by tag name on string 'request'
"""
err_msg = 'Can\'t use this function like this, read documentation'
if req_str is None and parent is None:
if xml_str is None and parent is None:
raise Exception(err_msg)
if req_str is not None and parent is not None:
if xml_str is not None and parent is not None:
raise Exception(err_msg)
if parent is not None:
root = parent
if req_str is not None:
root = self.xml_parse(req_str)
if xml_str is not None:
root = self.xml_parse(xml_str)
# Search element
for node in ElementTree(element=root).iter(tag=tag):
if node.tag == tag:
self.log.debug(MSG_FOUND_NODE.format(node.tag, node.text))
return node

def find_nodes(self, tag, xml_str=None, parent=None):
"""
Returns list of nodes obtained itering
by tag name on string 'request'
"""
err_msg = 'Can\'t use this function like this, read documentation'
if xml_str is None and parent is None:
raise Exception(err_msg)
if xml_str is not None and parent is not None:
raise Exception(err_msg)
if parent is not None:
root = parent
if xml_str is not None:
root = self.xml_parse(xml_str)
# Search element
nodes_found = list()
for node in ElementTree(element=root).iter(tag=tag):
if node.tag == tag:
self.log.debug(MSG_FOUND_NODE.format(node.tag, node.text))
nodes_found.append(node)
return nodes_found

def parse_node_value(self, node_value):
"""
Parse and validate XML value member and return it
parsed to each valid type
"""
value_node_string = self.find_node(
'string', parent=node_value)
value_node_struct = self.find_node(
'string', parent=node_value)
if value_node_string is not None:
return value_node_string.text
if value_node_struct is not None:
# TODO: i don't know how to do this yet
raise NotImplementedError(
'Response node_member struct not handled yet')


def xml_parse(self, xml_str):
"""
Parse request string and return it
Expand Down

0 comments on commit 21adff3

Please sign in to comment.