Database model custom JSONField values persisting between test cases












1















I'm using a Django database model to store objects corresponding to a remote ticket service. In testing this model, I'm running several tests to make sure that log messages work correctly for the database model - I'm using Django-nose to run these tests.



The database model looks something like this, using the JSONField from this StackOverflow answer with a small modification to support lists as well as dicts:



class TicketEntity(django.db.models.Model)
tickets = JSONField(null=True, blank=True, default=, serialize=True)
queued_ticket_data = JSONField(null=True, blank=True, default=, serialize=True)
...
@classmethod
def create(cls, *args, **kwargs):
instance = cls(*args, **kwargs)
instance.save()
return instance

def queue_output_for_ticket(self, log_data):
self.queued_ticket_data += [log_data]
self.save()

def push_ticket(self):
self.tickets += [self.queued_ticket_data]
self.queued_ticket_data =
self.save()
return True


The tests (in the order they appear to get run) look like this:



def test_ticket_entity_push_ticket(self):
entity = TicketEntity.create()
entity.queue_output_for_ticket("log output")
entity.queue_output_for_ticket("more log output")
entity.push_ticket()
self.assertEquals(entity.tickets, [[log_data, log_data_1]])
self.assertFalse(entity.queued_ticket_data)

def test_ticket_entity_queue_output_for_ticket(self):
entity = TicketEntity.create()
log_data = "Here's some output to log.nHere's another line of output.nAnd another."
entity.queue_output_for_ticket(log_data)
self.assertEquals(entity.queued_ticket_data, [log_data])


The first test passes, perfectly fine. The second test fails on that assert statement, because the entity.queued_ticket_data looks like this:



["log output", 
"more log output",
"Here's some output to log.nHere's another line of output.nAnd another."]


Those first two elements are there at the very start of the test, immediately after we call TicketEntity.create(). They shouldn't be there - the new instance should be clean because we're creating it from scratch.



Similarly, tickets is pre-filled as well. The TicketEntity has other fields that are not JSONFields, and they do not seem to exhibit this problem.



Can someone shed some light on why this problem might be happening, and what kind of modification we'd need for a fix?










share|improve this question


















  • 1





    This is a variant of the mutable default argument gotcha, and is specifically mentioned in the docs for JSONField.

    – Daniel Roseman
    Nov 15 '18 at 16:58











  • That seems to have been the problem, thanks! We didn't know that JSONField was already a thing, so we never thought to look in the documentation.

    – Green Cloak Guy
    Nov 15 '18 at 18:26






  • 1





    Possible duplicate of "Least Astonishment" and the Mutable Default Argument

    – Green Cloak Guy
    Nov 15 '18 at 18:27
















1















I'm using a Django database model to store objects corresponding to a remote ticket service. In testing this model, I'm running several tests to make sure that log messages work correctly for the database model - I'm using Django-nose to run these tests.



The database model looks something like this, using the JSONField from this StackOverflow answer with a small modification to support lists as well as dicts:



class TicketEntity(django.db.models.Model)
tickets = JSONField(null=True, blank=True, default=, serialize=True)
queued_ticket_data = JSONField(null=True, blank=True, default=, serialize=True)
...
@classmethod
def create(cls, *args, **kwargs):
instance = cls(*args, **kwargs)
instance.save()
return instance

def queue_output_for_ticket(self, log_data):
self.queued_ticket_data += [log_data]
self.save()

def push_ticket(self):
self.tickets += [self.queued_ticket_data]
self.queued_ticket_data =
self.save()
return True


The tests (in the order they appear to get run) look like this:



def test_ticket_entity_push_ticket(self):
entity = TicketEntity.create()
entity.queue_output_for_ticket("log output")
entity.queue_output_for_ticket("more log output")
entity.push_ticket()
self.assertEquals(entity.tickets, [[log_data, log_data_1]])
self.assertFalse(entity.queued_ticket_data)

def test_ticket_entity_queue_output_for_ticket(self):
entity = TicketEntity.create()
log_data = "Here's some output to log.nHere's another line of output.nAnd another."
entity.queue_output_for_ticket(log_data)
self.assertEquals(entity.queued_ticket_data, [log_data])


The first test passes, perfectly fine. The second test fails on that assert statement, because the entity.queued_ticket_data looks like this:



["log output", 
"more log output",
"Here's some output to log.nHere's another line of output.nAnd another."]


Those first two elements are there at the very start of the test, immediately after we call TicketEntity.create(). They shouldn't be there - the new instance should be clean because we're creating it from scratch.



Similarly, tickets is pre-filled as well. The TicketEntity has other fields that are not JSONFields, and they do not seem to exhibit this problem.



Can someone shed some light on why this problem might be happening, and what kind of modification we'd need for a fix?










share|improve this question


















  • 1





    This is a variant of the mutable default argument gotcha, and is specifically mentioned in the docs for JSONField.

    – Daniel Roseman
    Nov 15 '18 at 16:58











  • That seems to have been the problem, thanks! We didn't know that JSONField was already a thing, so we never thought to look in the documentation.

    – Green Cloak Guy
    Nov 15 '18 at 18:26






  • 1





    Possible duplicate of "Least Astonishment" and the Mutable Default Argument

    – Green Cloak Guy
    Nov 15 '18 at 18:27














1












1








1


1






I'm using a Django database model to store objects corresponding to a remote ticket service. In testing this model, I'm running several tests to make sure that log messages work correctly for the database model - I'm using Django-nose to run these tests.



The database model looks something like this, using the JSONField from this StackOverflow answer with a small modification to support lists as well as dicts:



class TicketEntity(django.db.models.Model)
tickets = JSONField(null=True, blank=True, default=, serialize=True)
queued_ticket_data = JSONField(null=True, blank=True, default=, serialize=True)
...
@classmethod
def create(cls, *args, **kwargs):
instance = cls(*args, **kwargs)
instance.save()
return instance

def queue_output_for_ticket(self, log_data):
self.queued_ticket_data += [log_data]
self.save()

def push_ticket(self):
self.tickets += [self.queued_ticket_data]
self.queued_ticket_data =
self.save()
return True


The tests (in the order they appear to get run) look like this:



def test_ticket_entity_push_ticket(self):
entity = TicketEntity.create()
entity.queue_output_for_ticket("log output")
entity.queue_output_for_ticket("more log output")
entity.push_ticket()
self.assertEquals(entity.tickets, [[log_data, log_data_1]])
self.assertFalse(entity.queued_ticket_data)

def test_ticket_entity_queue_output_for_ticket(self):
entity = TicketEntity.create()
log_data = "Here's some output to log.nHere's another line of output.nAnd another."
entity.queue_output_for_ticket(log_data)
self.assertEquals(entity.queued_ticket_data, [log_data])


The first test passes, perfectly fine. The second test fails on that assert statement, because the entity.queued_ticket_data looks like this:



["log output", 
"more log output",
"Here's some output to log.nHere's another line of output.nAnd another."]


Those first two elements are there at the very start of the test, immediately after we call TicketEntity.create(). They shouldn't be there - the new instance should be clean because we're creating it from scratch.



Similarly, tickets is pre-filled as well. The TicketEntity has other fields that are not JSONFields, and they do not seem to exhibit this problem.



Can someone shed some light on why this problem might be happening, and what kind of modification we'd need for a fix?










share|improve this question














I'm using a Django database model to store objects corresponding to a remote ticket service. In testing this model, I'm running several tests to make sure that log messages work correctly for the database model - I'm using Django-nose to run these tests.



The database model looks something like this, using the JSONField from this StackOverflow answer with a small modification to support lists as well as dicts:



class TicketEntity(django.db.models.Model)
tickets = JSONField(null=True, blank=True, default=, serialize=True)
queued_ticket_data = JSONField(null=True, blank=True, default=, serialize=True)
...
@classmethod
def create(cls, *args, **kwargs):
instance = cls(*args, **kwargs)
instance.save()
return instance

def queue_output_for_ticket(self, log_data):
self.queued_ticket_data += [log_data]
self.save()

def push_ticket(self):
self.tickets += [self.queued_ticket_data]
self.queued_ticket_data =
self.save()
return True


The tests (in the order they appear to get run) look like this:



def test_ticket_entity_push_ticket(self):
entity = TicketEntity.create()
entity.queue_output_for_ticket("log output")
entity.queue_output_for_ticket("more log output")
entity.push_ticket()
self.assertEquals(entity.tickets, [[log_data, log_data_1]])
self.assertFalse(entity.queued_ticket_data)

def test_ticket_entity_queue_output_for_ticket(self):
entity = TicketEntity.create()
log_data = "Here's some output to log.nHere's another line of output.nAnd another."
entity.queue_output_for_ticket(log_data)
self.assertEquals(entity.queued_ticket_data, [log_data])


The first test passes, perfectly fine. The second test fails on that assert statement, because the entity.queued_ticket_data looks like this:



["log output", 
"more log output",
"Here's some output to log.nHere's another line of output.nAnd another."]


Those first two elements are there at the very start of the test, immediately after we call TicketEntity.create(). They shouldn't be there - the new instance should be clean because we're creating it from scratch.



Similarly, tickets is pre-filled as well. The TicketEntity has other fields that are not JSONFields, and they do not seem to exhibit this problem.



Can someone shed some light on why this problem might be happening, and what kind of modification we'd need for a fix?







json django django-database django-nose






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 15 '18 at 16:26









Green Cloak GuyGreen Cloak Guy

3,0091721




3,0091721








  • 1





    This is a variant of the mutable default argument gotcha, and is specifically mentioned in the docs for JSONField.

    – Daniel Roseman
    Nov 15 '18 at 16:58











  • That seems to have been the problem, thanks! We didn't know that JSONField was already a thing, so we never thought to look in the documentation.

    – Green Cloak Guy
    Nov 15 '18 at 18:26






  • 1





    Possible duplicate of "Least Astonishment" and the Mutable Default Argument

    – Green Cloak Guy
    Nov 15 '18 at 18:27














  • 1





    This is a variant of the mutable default argument gotcha, and is specifically mentioned in the docs for JSONField.

    – Daniel Roseman
    Nov 15 '18 at 16:58











  • That seems to have been the problem, thanks! We didn't know that JSONField was already a thing, so we never thought to look in the documentation.

    – Green Cloak Guy
    Nov 15 '18 at 18:26






  • 1





    Possible duplicate of "Least Astonishment" and the Mutable Default Argument

    – Green Cloak Guy
    Nov 15 '18 at 18:27








1




1





This is a variant of the mutable default argument gotcha, and is specifically mentioned in the docs for JSONField.

– Daniel Roseman
Nov 15 '18 at 16:58





This is a variant of the mutable default argument gotcha, and is specifically mentioned in the docs for JSONField.

– Daniel Roseman
Nov 15 '18 at 16:58













That seems to have been the problem, thanks! We didn't know that JSONField was already a thing, so we never thought to look in the documentation.

– Green Cloak Guy
Nov 15 '18 at 18:26





That seems to have been the problem, thanks! We didn't know that JSONField was already a thing, so we never thought to look in the documentation.

– Green Cloak Guy
Nov 15 '18 at 18:26




1




1





Possible duplicate of "Least Astonishment" and the Mutable Default Argument

– Green Cloak Guy
Nov 15 '18 at 18:27





Possible duplicate of "Least Astonishment" and the Mutable Default Argument

– Green Cloak Guy
Nov 15 '18 at 18:27












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53323834%2fdatabase-model-custom-jsonfield-values-persisting-between-test-cases%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53323834%2fdatabase-model-custom-jsonfield-values-persisting-between-test-cases%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine