Hello, We're using zope.sendmail to send mail from our applications. These applications are built on top of a more generic application library. It is this application library that depends on zope.sendmail. This application library listens for certain events and then can decide to send out an email. Obviously, when running the tests for the concrete application no mail is allowed to be actually sent. Zope.sendmail explains in its README.txt that the developer using zope.sendmail should himself take care of not sending emails (by setting up a test layer for example, that would register a no-op IMailDelivery utility). I had hoped that somehow zope.sendmail would automagically "detect" it is used during test runs and then would not send out any mails. I dug around in zope.testing and found the cleanup module that seems to provide (if I understand correctly) a global registry of things to cleanup after tests. I wonder if this could be extended to also be able to register routines for globally setting up stuff - in this case it could stub the mail delivery so that never ever any mail is actually send out when running tests. Questions: 1) how do others make sure that applications that directly or indirectly trigger sending mails do not actually send during testing? 2) am I on the right track thinking a "set up" equivalent of zope.testing.cleanup could be useful for these cases? kind regards, jw -- Jan-Wijbrand Kolman
Hello, I'd rather use a mailer stub for testing. Like the one in zope.sendmail.tests.test_mailer.py ... class SMTP(object): ... Something like this can be setup for individual tests with <utility name="mailer-name" provides="zope.sendmail.interfaces.IMailer" factory="your.own.mailerFactory" /> def mailerFactory(): mailer = SMTPMailer() mailer.smtp = SMTP return mailer Tuesday, August 25, 2009, 2:48:57 PM, you wrote: JWK> Hello, JWK> We're using zope.sendmail to send mail from our applications. These JWK> applications are built on top of a more generic application library. It JWK> is this application library that depends on zope.sendmail. This JWK> application library listens for certain events and then can decide to JWK> send out an email. JWK> Obviously, when running the tests for the concrete application no mail JWK> is allowed to be actually sent. JWK> Zope.sendmail explains in its README.txt that the developer using JWK> zope.sendmail should himself take care of not sending emails (by setting JWK> up a test layer for example, that would register a no-op IMailDelivery JWK> utility). JWK> I had hoped that somehow zope.sendmail would automagically "detect" it JWK> is used during test runs and then would not send out any mails. JWK> I dug around in zope.testing and found the cleanup module that seems to JWK> provide (if I understand correctly) a global registry of things to JWK> cleanup after tests. I wonder if this could be extended to also be able JWK> to register routines for globally setting up stuff - in this case it JWK> could stub the mail delivery so that never ever any mail is actually JWK> send out when running tests. JWK> Questions: JWK> 1) how do others make sure that applications that directly or indirectly JWK> trigger sending mails do not actually send during testing? JWK> 2) am I on the right track thinking a "set up" equivalent of JWK> zope.testing.cleanup could be useful for these cases? JWK> kind regards, JWK> jw JWK> -- JWK> Jan-Wijbrand Kolman JWK> _______________________________________________ JWK> Zope-Dev maillist - Zope-Dev@zope.org JWK> http://mail.zope.org/mailman/listinfo/zope-dev JWK> ** No cross posts or HTML encoding! ** JWK> (Related lists - JWK> http://mail.zope.org/mailman/listinfo/zope-announce JWK> http://mail.zope.org/mailman/listinfo/zope ) -- Best regards, Adam GROSZER mailto:agroszer@gmail.com -- Quote of the day: To be upset over what you don't have is to waste what you do have. - Ken S. Keyes
Adam GROSZER wrote:
Hello,
I'd rather use a mailer stub for testing. Like the one in zope.sendmail.tests.test_mailer.py
... class SMTP(object): ...
Something like this can be setup for individual tests with
<utility name="mailer-name" provides="zope.sendmail.interfaces.IMailer" factory="your.own.mailerFactory" />
def mailerFactory(): mailer = SMTPMailer() mailer.smtp = SMTP return mailer
Right, I see. However, what I meant to ask is if there is a way to have the registration of such a stub to be more or less automagically done during test runs by the zope.sendmail package instead of having to think about this over and over again in the packages directly or indirectly depending on it. I *thought* to see a way of getting rid of global data in zope.testing.cleanup, and I wonder if we could think of a way to set up global data in a similar manner regards, jw
Hello, I think automagic things are evil. Later if you realize that you don't need them you have to fight to get rid of them. Tuesday, August 25, 2009, 4:19:30 PM, you wrote: JWK> Adam GROSZER wrote:
Hello,
I'd rather use a mailer stub for testing. Like the one in zope.sendmail.tests.test_mailer.py
... class SMTP(object): ...
Something like this can be setup for individual tests with
<utility name="mailer-name" provides="zope.sendmail.interfaces.IMailer" factory="your.own.mailerFactory" />
def mailerFactory(): mailer = SMTPMailer() mailer.smtp = SMTP return mailer
JWK> Right, I see. However, what I meant to ask is if there is a way to have JWK> the registration of such a stub to be more or less automagically done JWK> during test runs by the zope.sendmail package instead of having to think JWK> about this over and over again in the packages directly or indirectly JWK> depending on it. JWK> I *thought* to see a way of getting rid of global data in JWK> zope.testing.cleanup, and I wonder if we could think of a way to set up JWK> global data in a similar manner JWK> regards, JWK> jw JWK> _______________________________________________ JWK> Zope-Dev maillist - Zope-Dev@zope.org JWK> http://mail.zope.org/mailman/listinfo/zope-dev JWK> ** No cross posts or HTML encoding! ** JWK> (Related lists - JWK> http://mail.zope.org/mailman/listinfo/zope-announce JWK> http://mail.zope.org/mailman/listinfo/zope ) -- Best regards, Adam GROSZER mailto:agroszer@gmail.com -- Quote of the day: Success without honor is an unseasoned dish; it will satisfy your hunger, but it won't taste good. - Joe Paterno
Jan-Wijbrand Kolman wrote:
Zope.sendmail explains in its README.txt that the developer using zope.sendmail should himself take care of not sending emails (by setting up a test layer for example, that would register a no-op IMailDelivery utility).
Why not just use testfixtures [1] and Mock [2] to replace the SMTP class in your testcase? from mock import Mock from testfixtures import replace @replace('smtplib.SMTP',Mock()) def test_mystuff(self): ... That way you can check the right smtp calls are made, if you want to, and there's no chance of mail being sent? If you're doing a lot of tests, you might want to do: from mock import Mock from testfixtures import Replacer class MyTests(TestCase): def setUp(self): self.r = Replacer self.r.replace('smtplib.SMTP',Mock()) def tearDown(self): self.r.restore() This latter technique would probably work in a Layer too... cheers, Chris [1] http://pypi.python.org/pypi/testfixtures [2] http://pypi.python.org/pypi/mock -- Simplistix - Content Management, Batch Processing & Python Consulting - http://www.simplistix.co.uk
Chris Withers wrote:
Jan-Wijbrand Kolman wrote:
Zope.sendmail explains in its README.txt that the developer using zope.sendmail should himself take care of not sending emails (by setting up a test layer for example, that would register a no-op IMailDelivery utility).
Why not just use testfixtures [1] and Mock [2] to replace the SMTP class in your testcase?
from mock import Mock from testfixtures import replace @replace('smtplib.SMTP',Mock()) def test_mystuff(self): ...
That way you can check the right smtp calls are made, if you want to, and there's no chance of mail being sent?
My point is that I have to make sure the fixtures/mocking is done even in indirect consumers of zope.sendmail. What I mean is, if I run the tests of my application Foo, that uses an application library MyLib where this MyLib library listens for events that can trigger email being send, I need to *not forget* to use these fixtures or mocks in the test setup of Foo. Even if the code of Foo does not itself call zope.sendmail. I had hoped there would be a way for either zope.sendmail, or perhaps for MyLib, to make sure that no mail is ever send when running tests of Foo.
This latter technique would probably work in a Layer too...
Right, that might work - I would need to define a test layer in MyLib and not forget to use this base layer for the tests for Foo. It would be slightly better, but it is still something I or a team member could forget. Generally that would not be so much of a problem, however I would hate to unintentionally send out mail... Still I wonder about zope.testing.cleanup... Thanks for the replies so far! regards, jw
On Tue, Aug 25, 2009 at 05:12:53PM +0200, Jan-Wijbrand Kolman wrote:
My point is that I have to make sure the fixtures/mocking is done even in indirect consumers of zope.sendmail.
What I mean is, if I run the tests of my application Foo, that uses an application library MyLib where this MyLib library listens for events that can trigger email being send, I need to *not forget* to use these fixtures or mocks in the test setup of Foo. Even if the code of Foo does not itself call zope.sendmail.
But MyLib cannot send email if your test fixture doesn't set up and register a fully-functional email-sending utility! Find the place where your test fixtures do that and replace it with a stub no-email-sending utility.
I had hoped there would be a way for either zope.sendmail, or perhaps for MyLib, to make sure that no mail is ever send when running tests of Foo.
Some kind of a global switch to unconditionally disable email delivery in zope.sendmail would be useful sometimes, but I'm afraid of it clouding the issue too much.
This latter technique would probably work in a Layer too...
Right, that might work - I would need to define a test layer in MyLib and not forget to use this base layer for the tests for Foo. It would be slightly better, but it is still something I or a team member could forget. Generally that would not be so much of a problem, however I would hate to unintentionally send out mail...
Still I wonder about zope.testing.cleanup...
You cannot really depend on the order of cleanup handlers. There already is a cleanup handler that clears the whole component registry, including any and all email utilities. PlacelessSetup invokes all cleanup handlers. If your tests use PlacelessSetup (and unit tests generally do), and if they can send mail, then it means you're registering an email utility after the cleanup handlers have run, and therefore a cleanup handler cannot possibly disable it. Functional tests that want to preserve some kind of component configuration between tests cannot use PlacelessSetup (or CleanUp), since the aforementioned cleanup handler would clear the component registry and break all your tests. Marius Gedminas -- http://pov.lt/ -- Zope 3 consulting and development
participants (4)
-
Adam GROSZER -
Chris Withers -
Jan-Wijbrand Kolman -
Marius Gedminas