【问题标题】:How can i update class variable by calling a class method from a derived class如何通过从派生类调用类方法来更新类变量
【发布时间】:2018-03-06 18:39:44
【问题描述】:

我正在为我的测试目的开发一个名为 dbtest 的包。这个包是因为我使用 MySQLdb 连接数据库,因此在测试时编写 sql 查询是非常繁琐的任务。所以我创建了一个新包,所有查询都可以使用单独的函数访问。我避免使用 django ORM,因为我的数据库表有多个外键和主键。

下面是包装的一部分。

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='vishnu@clartrum.com')

    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='vishnu@clartrum.com')

包中的insert_table 执行sql 中的插入操作,delete 方法删除用户的最后一个条目。 empty.sql 为数据库创建表。 实际上,当我运行测试时,最终 flag_user 应该只包含[['vishnu']]。但我得到[['vishnu'],['vishnu']],这是因为拆卸中的删除功能不会更新值。

我认为这是由于类实例?我说的对吗?

【问题讨论】:

  • 也许我遗漏了一些东西,但为什么你在 package.py 中的方法没有缩进到类中?另外,你能告诉我们 delete_table 函数吗?
  • delete_table 只不过是一个 sql 查询 cursor=dbcon.cursor() query="delete from user where username=%s" cursor.execute(query,'vishnu') dbcon.commit() cursor.close()
  • @Ben 请调查一下
  • tablenamedeleteuser_table 中来自哪里? (你当然不应该在delete_table 中使用eval。)
  • Django ORM 开销在我过去十年从事的数十个 django 项目中从来都不是问题(当然,假设你学会了正确使用它,但这只是常识)。在决定“放慢速度”之前,您是否真的关心分析任何内容?

标签: django python-2.7 class subclassing class-variables


【解决方案1】:

这里:

class testcase(TestCase):
    flag_user=[]

您将flag_user 创建为类属性(由所有实例共享)。

那么这里:

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

您附加到(类级别)flag_user 属性(通过实例访问它,但它仍然是类属性)

但是在这里:

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

您在实例本身上创建一个flag_user 属性,该属性与同名类属性完全断开。

最简单的解决方案是从一开始就使用实例属性,而不是使用类属性:

# package.py

from django.test import TestCase
dbcon='connector'

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

别忘了在子类中调用testcase.setUp

# tests.py

from package import testcase
class showfiles(testcase):

    def setUp(self):
      super(showfile, self).setUp()
      self.user_table(username='vishnu',email='vishnu@clartrum.com')

如果你真的想要一个类属性(我无法想象你为什么会但是......),另一种解决方案是修改testcase.delete(),以便它真正清除flag_user 类属性而不是创建实例属性,这是通过明确要求 python 重新绑定类本身的属性来完成的(type(obj) 返回 obj.__class__ 这是实例所属的类):

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

【讨论】:

  • 否则最好在所有方法中使用testcase.flag_user,不是吗?
  • 当然,我需要类属性。据我所知,showfiles() 中的每个方法都有一个self,它依次引用测试用例类,而 showfiles() 方法中的每个self 都是测试用例的不同实例。我的知识正确与否?
  • 是的 self 是当前实例。但是由于您在tearDown 方法中调用delete("user"),因此每次测试都会调用它,因此将flag_user 设置为类属性是毫无用处的。你到底用这个属性做什么?
  • flag_user 用于跟踪用户表条目。它在delete() 中用于访问用户中的最后一个条目。 delete() 只删除最后一个条目。
  • 所以当我删除一个条目时,我也必须删除轨道
猜你喜欢
  • 2023-03-15
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 2013-09-23
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
  • 2013-09-28
相关资源
最近更新 更多