text: import datetime
  import json
  import unittest
  
  import requests
  
  URL = ("http://", "127.0.0.1", ":", "8000", "/")
  
  HEADERS = {'Content-Type': 'application/json'}
  
  
  class FilledUserTests(unittest.TestCase):
      @classmethod
      def setUpClass(cls):
          requests.get(''.join(URL + ('debug/clear/',)))
          params = {'name': 'gert', 'mailAddress': 'gertMail'}
          r = requests.post(''.join(URL + ('user', '/')), headers=HEADERS, data=json.dumps(params))
          result = r.json()
          user_1 = result['id']
          params = {'name': 'bar', 'mailAddress': 'barMail'}
          r = requests.post(''.join(URL + ('user', '/')), headers=HEADERS, data=json.dumps(params))
          result = r.json()
          user_2 = result['id']
          cls.names = ['gert', 'bar']
          cls.ids = [user_1, user_2]
  
      def test_list_2_users(self):
          r = requests.get(''.join(URL + ('user',)), headers=HEADERS)
          self.assertEqual(200, r.status_code)
          self.assertEqual('application/json', r.headers['Content-Type'])
          users = json.loads(r.text)
          self.assertEqual(2, users.get('overall_count'))
          self.assertEqual(100, users.get('limit'))
          self.assertEqual(0, users.get('offset'))
          entries = users['entries']
          self.assertIsInstance(entries, list)
          self.assertEqual(2, len(entries))
          for i in range(0, 1):
              with self.subTest(i=i):
                  self.assertEqual(self.names[i], entries[i].get('name'))
                  self.assertEqual(self.ids[i], entries[i]['id'])
                  self.assertEqual(0, entries[i].get('balance'))
                  self.assertIsNone(entries[i].get('last_transaction'))
  
      def test_list_users_empty_offset(self):
          r = requests.get(''.join(URL + ('user',)), headers=HEADERS, params={'offset': 2, 'limit': 1})
          self.assertEqual(200, r.status_code)
          self.assertEqual('application/json', r.headers['Content-Type'])
          users = json.loads(r.text)
          self.assertEqual(2, users.get('overall_count'))
          self.assertEqual(1, users.get('limit'))
          self.assertEqual(2, users.get('offset'))
          entries = users['entries']
          self.assertIsInstance(entries, list)
          self.assertEqual(0, len(entries))
  
      def test_load_user_by_id(self):
          for i, name in enumerate(self.names):
              r = requests.get(''.join(URL + ('user', '/', str(self.ids[i]))), headers=HEADERS)
              self.assertEqual(200, r.status_code)
              self.assertEqual('application/json', r.headers['Content-Type'])
              user = json.loads(r.text)
              self.assertEqual(name, user.get('name'))
              self.assertEqual(self.ids[i], user.get('id'))
              self.assertEqual(0, user.get('balance'))
              self.assertIsNone(user.get('last_transaction'))
  
  
  class FilledTransactionsTests(unittest.TestCase):
      @classmethod
      def setUpClass(cls):
          requests.get(''.join(URL + ('debug/clear/',)))
          params = {'name': 'gert', 'mailAddress': 'gertMail'}
          r = requests.post(''.join(URL + ('user', '/')), headers=HEADERS, data=json.dumps(params))
          result = r.json()
          user_1 = result['id']
          params = {'name': 'bar', 'mailAddress': 'barMail'}
          r = requests.post(''.join(URL + ('user', '/')), headers=HEADERS, data=json.dumps(params))
          result = r.json()
          user_2 = result['id']
          cls.names = ['gert', 'bar']
          cls.ids = [user_1, user_2]
          cls.transactions = {user_1: [1000, -500, -150],
                              user_2: [2000, -250, -50]}
          for user_id, value_list in cls.transactions.items():
              for value in value_list:
                  FilledTransactionsTests.add_transaction_to_user(user_id, value=value)
  
      @staticmethod
      def add_transaction_to_user(user_id, value):
          params = {'value': value}
          r = requests.post(''.join((URL + ('user', '/', str(user_id), '/', 'transaction', '/'))),
                            headers=HEADERS,
                            data=json.dumps(params))
          assert 201 == r.status_code
  
      def test_load_user_by_id(self):
          for i, name in enumerate(self.names):
              user_id = self.ids[i]
              r = requests.get(''.join(URL + ('user', '/', str(user_id))), headers=HEADERS)
              self.assertEqual(200, r.status_code)
              self.assertEqual('application/json', r.headers['Content-Type'])
              user = json.loads(r.text)
              self.assertEqual(name, user.get('name'))
              self.assertEqual(self.ids[i], user.get('id'))
              balance = sum(self.transactions.get(user_id, []))
              self.assertEqual(balance, user.get('balance'))
              self.assertIsNotNone(user.get('last_transaction'))
              now = datetime.datetime.utcnow()
              last_transaction = datetime.datetime.strptime(user['last_transaction'], '%Y-%m-%dT%H:%M:%S.%fZ')
              self.assertGreater(20, (now - last_transaction).total_seconds())
  
      def test_load_user_transactions(self):
          for i, name in enumerate(self.names):
              user_id = self.ids[i]
              r = requests.get(''.join(URL + ('user', '/', str(user_id), '/', 'transaction',)), headers=HEADERS)
              self.assertEqual(200, r.status_code)
              self.assertEqual('application/json', r.headers['Content-Type'])
              transactions = json.loads(r.text)
              self.assertEqual(len(self.transactions.get(user_id)), transactions.get('overall_count'))
              self.assertEqual(100, transactions.get('limit'))
              self.assertEqual(0, transactions.get('offset'))
              self.assertIsInstance(transactions['entries'], list)
              entries = transactions['entries']
              self.assertEqual(len(self.transactions.get(user_id)), len(entries))
              for j, entry in enumerate(entries):
                  self.assertEqual(self.transactions.get(user_id)[j], entry['value'])
                  self.assertEqual(user_id, entry['user'])
  
      def test_load_user_transactions_offset(self):
          for i, name in enumerate(self.names):
              user_id = self.ids[i]
              r = requests.get(''.join(URL + ('user', '/', str(user_id), '/', 'transaction',)), headers=HEADERS,
                               params={'limit': 1, 'offset': 2})
              self.assertEqual(200, r.status_code)
              self.assertEqual('application/json', r.headers['Content-Type'])
              transactions = json.loads(r.text)
              self.assertEqual(len(self.transactions.get(user_id)), transactions.get('overall_count'))
              self.assertEqual(1, transactions.get('limit'))
              self.assertEqual(2, transactions.get('offset'))
              self.assertIsInstance(transactions['entries'], list)
              entries = transactions['entries']
              self.assertEqual(1, len(entries))
              for j, entry in enumerate(entries):
                  self.assertEqual(self.transactions.get(user_id)[j + 2], entry['value'])
                  self.assertEqual(user_id, entry['user'])
  
      def test_load_user_single_transaction(self):
          for user_id in self.transactions.keys():
              r = requests.get(''.join(URL + ('user', '/', str(user_id), '/', 'transaction',)), headers=HEADERS)
              self.assertEqual(200, r.status_code)
              transactions = json.loads(r.text)
              entries = transactions['entries']
              for j, entry in enumerate(entries):
                  with self.subTest(transaction_id=entry['id']):
                      self.assertEqual(self.transactions.get(user_id)[j], entry['value'])
                      self.assertEqual(user_id, entry['user'])
                      self.assert_user_transaction(entry['id'], entry['value'], user_id)
  
      def test_load_transactions_offset(self):
          r = requests.get(''.join(URL + ('transaction',)), headers=HEADERS,
                           params={'limit': 1, 'offset': 2})
          self.assertEqual(200, r.status_code)
          self.assertEqual('application/json', r.headers['Content-Type'])
          transactions = json.loads(r.text)
          total_count = sum([len(x) for x in self.transactions.values()])
          self.assertEqual(total_count, transactions.get('overall_count'))
          self.assertEqual(1, transactions.get('limit'))
          self.assertEqual(2, transactions.get('offset'))
          self.assertIsInstance(transactions['entries'], list)
          entries = transactions['entries']
          self.assertEqual(1, len(entries))
          for j, entry in enumerate(entries):
              user_id = entry['user']
              self.assertIn(entry['value'], self.transactions.get(user_id))
  
      def test_load_single_transaction(self):
          r = requests.get(''.join(URL + ('transaction',)), headers=HEADERS)
          self.assertEqual(200, r.status_code)
          transactions = json.loads(r.text)
          entries = transactions['entries']
          for j, entry in enumerate(entries):
              with self.subTest(transaction_id=entry['id']):
                  user_id = entry['user']
                  self.assertIn(entry['value'], self.transactions.get(user_id))
                  self.assert_user_transaction(entry['id'], entry['value'], user_id)
  
      def assert_user_transaction(self, transaction_id, value, user_id):
          r = requests.get(
              ''.join(URL + ('user', '/', str(user_id), '/', 'transaction', '/', str(transaction_id))),
              headers=HEADERS)
          self.assertEqual(200, r.status_code, msg=r.text)
          self.assertEqual('application/json', r.headers['Content-Type'])
          transaction = r.json()
          self.assertEqual(transaction_id, transaction['id'])
          self.assertEqual(user_id, transaction['user'])
          self.assertEqual(value, transaction['value'])
          now = datetime.datetime.utcnow()
          last_transaction = datetime.datetime.strptime(transaction['create_date'], '%Y-%m-%dT%H:%M:%S.%fZ')
          self.assertGreater(20, (now - last_transaction).total_seconds())
  