-2

I am developing a package for my testing purpose called dbtest. This package is because i am using MySQLdb for connecting databases and hence it is very tedious task to write sql queries while testing. So i created a new package and all queries can be accessed with separate functions. I avoided django ORM because my database table have multiple foreign keys and primary keys.

Below present is a part of the package.

package.py

from django.test import TestCase
dbcon='connector'
class testcase(TestCase):
    flag_user=[]

@classmethod                                                               
def setUpClass(cls):

    global dbcon
    dbcon=MySQLdb.connect(host=dbHost,port=dbPort,user=dbUser,passwd=dbPasswd,db=dbname)
    super(testcase, cls).setUpClass()

    cursor = dbcon.cursor()
    sql=open("empty.sql").read()
    cursor.execute(sql)
    cursor.close()

    views.MySQLdb=Mockdb()

@classmethod
def tearDownClass(cls):
   dbcon.close()

def user_table(self,username=username,email=email):

    cache=[username]
    self.flag_user.append(cache)
    cmpdata=(username,email)
    insert_table(tablename_user,cmpdata)

def delete(self,table):
    last_entry=self.flag_user[-1]
    query_user = 'delete from USER where USERNAME=%s'
    cursor=dbcon.cursor()
    query=eval('query_%s'%table)
    cursor.execute(query,last_entry)
    dbcon.commit()
    del self.flag_user[-1]

tests.py

from package import testcase
class showfiles(testcase):

    def setUp(self):
      print "setup2"
      self.user_table(username='vishnu',email='[email protected]')

    def tearDown(self):
      print "teardown2"
      self.delete("user")

    def test_1(self):
      print "test dbtest link feature"


    def test_2(self):
      print "test health/errorfiles with valid device"
      self.user_table(username='vishnu',email='[email protected]')

The insert_table in package execute insert operation in sql and delete method deletes the last entry from user. empty.sql creates tables for the database. Actually when i run the tests, finally the flag_user should contain only [['vishnu']]. But i get [['vishnu'],['vishnu']] and this is because delete function in teardown doesn't updating the value.

I think this is due to class instances ? Am i right or not?

18
  • Maybe I'm missing something but why aren't your methods in package.py indented to be within the class? Also, can you show us the delete_table function? Commented Sep 25, 2017 at 18:02
  • delete_table is nothing but a sql query cursor=dbcon.cursor() query="delete from user where username=%s" cursor.execute(query,'vishnu') dbcon.commit() cursor.close() Commented Sep 25, 2017 at 18:12
  • @Ben please look into that Commented Sep 25, 2017 at 18:17
  • 1
    Where is tablename coming from in delete and user_table? (And you certainly shouldn't be using eval in delete_table.) Commented Sep 25, 2017 at 18:36
  • 2
    Django ORM overhead has never been an issue in any of the dozens django projects I worked on in the past ten years (assuming you learn to use it properly of course but that's just plain common sense). Did you actually care profiling anything before deciding it was "to slow"? Commented Sep 25, 2017 at 18:38

1 Answer 1

1

Here :

class testcase(TestCase):
    flag_user=[]

you create flag_user as a class attribute (shared by all instances).

Then here:

def user_table(self,username=username,email=email):
    cache=[username]
    self.flag_user.append(cache)

You append to the (class level) flag_user attribute (it's accessed thru the instance but it's still the class attribute)

But here:

def delete(self,table):
    delete_table(tablename)
    self.flag_user=[]

you create a flag_user attribute on the instance itself, which is totally disconnected from the eponym class attribute.

The simplest solution is to use an instance attribute right from the start instead of using a class attribute:

# package.py

from django.test import TestCase
dbcon='connector'

class testcase(TestCase):
    def setUp(self): 
        self.flag_user = []

and don't forget to call testcase.setUp in child classes:

# tests.py

from package import testcase
class showfiles(testcase):

    def setUp(self):
      super(showfile, self).setUp()
      self.user_table(username='vishnu',email='[email protected]')

The alternative solution if you really want a class attribute (I can't imagine why you would but...) is to modify testcase.delete() so it really clears the flag_user class attribute instead of creating an instance attribute, which is done by explicitely asking python to rebind the attribute on the class itself (type(obj) returns obj.__class__ which is the class the instance belongs to):

def delete(self,table):
    delete_table(tablename)
    type(self).flag_user = []
Sign up to request clarification or add additional context in comments.

11 Comments

Or otherwise it is better to use testcase.flag_user in all methods, isn't it?
Of course, i need class attributes. Up to my knowledge, each method in showfiles() have a self which in turns refer to testcase class and each self in showfiles() methods are different instances of testcase. My knowledge is correct or not?
Yes self is the current instance. But since you call delete("user") in the tearDown method, it will be called for each test, so making flag_user a class attribute is just plain useless. What are you using this attribute for actually ?
flag_user used to keep the track of user table entry. It is used in delete() for accessing the last entry in user. delete() only delete the last entry.
So when i delete an entry and i have to erase the track also
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.