First time I write the tests before the actual code. All fit in the same module.
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from os.path import join as path_join
from xmlrpclib import Fault, ServerProxy
XMLRPC_URL = 'xmlrpc/2'
class Model(object):
def __init__(self, host, db, uid, pwd, model):
self._object_api = ServerProxy( path_join(host, XMLRPC_URL, 'object') )
self._db = db
self._uid = uid
self._pwd = pwd
self._model = model
def _execute_kw(self, method, *args, **kwargs):
return self._object_api.execute_kw(self._db, self._uid, self._pwd,
self._model, method, args, kwargs)
def execute(self, method, *args, **kwargs):
"""Execute a method, with provide args and kwargs."""
return self._execute_kw(method, *args, **kwargs)
def search(self, domain=None, **kwargs):
"""Returns a list of ids.
kwargs: offset, limit, order, context, count
"""
if domain is None:
domain = []
return self._execute_kw('search', domain, **kwargs)
def search_count(self, domain=None, **kwargs):
"""Returns the number of records.
kwargs: context
"""
if domain is None:
domain = []
return self._execute_kw('search_count', domain, **kwargs)
def search_read(self, domain=None, **kwargs):
"""Returns a list of dictionnaries, containing values.
kwargs: fields, offset, limit, order, context
"""
if domain is None:
domain = []
return self._execute_kw('search_read', domain, **kwargs)
def create(self, vals, **kwargs):
"""Creates a new record, returns its database id.
kwargs: context
"""
return self._execute_kw('create', vals, **kwargs)
def write(self, ids, vals, **kwargs):
"""Modify records.
kwargs: context
"""
return self._execute_kw('write', ids, vals, **kwargs)
def unlink(self, ids, **kwargs):
"""Deletes records.
kwargs: context
"""
return self._execute_kw('unlink', ids, **kwargs)
class ObjectApi(object):
def __init__(self, host, db, login, pwd):
api_common = ServerProxy( path_join(host, XMLRPC_URL, 'common') )
uid = api_common.authenticate(db, login, pwd, {})
self._host = host
self._db = db
self._uid = uid
self._pwd = pwd
def get_model(self, model):
return Model(self._host, self._db, self._uid, self._pwd, model)
#########
# TESTS #
#########
import unittest
TESTING_ARGS = ["http://localhost:8069", "demo", "admin", "admin"]
class TestOdooApi(unittest.TestCase):
def setUp(self):
obj_api = ObjectApi(*TESTING_ARGS)
self.obj_api = obj_api
ResUsers = obj_api.get_model('res.users')
self.ResUsers = ResUsers
self.johnsmith_id = ResUsers.create({ 'name': 'John Smith',
'login': 'johnsmith' })
def tearDown(self):
self.ResUsers.unlink([self.johnsmith_id])
def test_search(self):
# return type
ids = self.ResUsers.search()
self.assertIsInstance(ids, list)
self.assertTrue(len(ids) > 0)
# with domain
ids = self.ResUsers.search([('login', '=', 'johnsmith')])
self.assertTrue(ids)
# with zero results
ids = self.ResUsers.search([('login', '=', False)])
self.assertIsInstance(ids, list)
self.assertFalse(ids)
def test_search_read(self):
# return type
records = self.ResUsers.search_read(fields=['name'])
self.assertIsInstance(records, list)
self.assertIsInstance(records[0], dict)
self.assertTrue(len(records) > 0)
# with domain
records = self.ResUsers.search_read([('login', '=', 'johnsmith')], fields=['name'])
self.assertEqual(records[0]['name'], 'John Smith')
# with zero results
records = self.ResUsers.search_read([('login', '=', False)])
self.assertIsInstance(records, list)
self.assertFalse(records)
def test_search_count(self):
# return type
count = self.ResUsers.search_count()
self.assertIsInstance(count, int)
self.assertTrue(count > 0)
# with domain
count = self.ResUsers.search_count([('login', '=', 'johnsmith')])
self.assertEqual(count, 1)
# with zero results
count = self.ResUsers.search_count([('login', '=', False)])
self.assertIsInstance(count, int)
self.assertEqual(count, 0)
def test_create_unlink(self):
user_id = self.ResUsers.create({ 'name': 'John Doe', 'login': 'johndoe' })
self.assertTrue(user_id)
# verify create
records = self.ResUsers.search_read([('login', '=', 'johndoe')], fields=['name'])
self.assertEqual(records[0]['name'], 'John Doe')
self.ResUsers.unlink([user_id])
# verify unlink
count = self.ResUsers.search_count([('login', '=', 'johndoe')])
self.assertEqual(count, 0)
def test_write(self):
self.ResUsers.write([self.johnsmith_id], { 'name': 'John Doe' })
# verify write
records = self.ResUsers.search_read([('login', '=', 'johnsmith')], fields=['name'])
self.assertEqual(records[0]['name'], 'John Doe')
def test_execute(self):
# return type
fields = self.ResUsers.execute('fields_get',
attributes=['string', 'help', 'type'])
self.assertIsInstance(fields, dict)
# non existing function
# unfortunately, we can only catch the xmlrpclib.Fault exception,
# and not the AttributeError raised on the server side
with self.assertRaises(Fault) as cm:
self.ResUsers.execute('function_that_will_raise_an_error')
if __name__ == '__main__':
"""Odoo api, by VimeXcom.
Running this module from the command line will test it, assuming:
1. you have a local Odoo up and running with:
- host: http:localhost:8069
- database: demo
- login: admin
- password: admin
2. the database is just installed with demo data, and nothing was modified
Import it with Python from a terminal or a script to use it on your own server.
"""
unittest.main()
Are the tests relevant ? Should I put the tests in a separate module ?