Re: [openstack-dev] Proposal for including fake implementations in python-client packages

2013-07-04 Thread Joe Gordon
On Wed, Jul 3, 2013 at 6:19 PM, Christopher Armstrong 
chris.armstr...@rackspace.com wrote:

 On Tue, Jul 2, 2013 at 11:38 PM, Robert Collins
 robe...@robertcollins.net wrote:
  Radix points out I missed the naunce that you're targeting the users
  of python-novaclient, for instance, rather than python-novaclient's
  own tests.
 
 
  On 3 July 2013 16:29, Robert Collins robe...@robertcollins.net wrote:
 
  What I'd like is for each client library, in addition to the actual
  implementation, is that they ship a fake, in-memory, version of the
 API. The
  fake implementations should take the same arguments, have the same
 return
  values, raise the same exceptions, and otherwise be identical, besides
 the
  fact
  that they are entirely in memory and never make network requests.
 
  So, +1 on shipping a fake reference copy of the API.
 
  -1 on shipping it in the client.
 
  The server that defines the API should have two implementations - the
  production one, and a testing fake. The server tests should exercise
  *both* code paths [e.g. using testscenarios] to ensure there is no
  skew between them.
 
  Then the client tests can be fast and efficient but not subject to
  implementation skew between fake and prod implementations.
 
  Back on Launchpad I designed a similar thing, but with language
  neutrality as a goal :
 
 https://dev.launchpad.net/ArchitectureGuide/ServicesRequirements#Test_fake
 
  And in fact, I think that that design would work well here, because we
  have multiple language bindings - Python, Ruby, PHP, Java, Go etc, and
  all of them will benefit from a low(ms or less)-latency test fake.
 
  So taking the aspect I missed into account I'm much happier with the
  idea of shipping a fake in the client, but... AFAICT many of our
  client behaviours are only well defined in the presence of a server
  anyhow.
 
  So it seems to me that a fast server fake can be used in tests of
  python-novaclient, *and* in tests of code using python-novaclient
  (including for instance, heat itself), and we get to write it just
  once per server, rather than once per server per language binding.
 
  -Rob


 I want to make sure I understond you. Let's say I have a program named
 cool-cloud-tool, and it uses python-novaclient, python-keystoneclient,
 and three other clients for OpenStack services. You're suggesting that
 its test suite should start up instances of all those OpenStack
 services with in-memory or otherwise localized backends, and
 communicate with them using standard python-*client functionality?

 I can imagine that being a useful thing, if it's very easy to do, and
 won't increase my test execution time too much.


The easiest way to do this would be to set up a devstack instance to run
your tests against, but that would increase test execution time by at least
a few minutes.  So although something like this would not work well for
unit tests it could be useful for integration tests.

Also I do not know of anyone using this for this type of testing yet, but
someone always has to be first.



 --
 IRC: radix
 Christopher Armstrong
 Rackspace

 ___
 OpenStack-dev mailing list
 OpenStack-dev@lists.openstack.org
 http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

___
OpenStack-dev mailing list
OpenStack-dev@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] Proposal for including fake implementations in python-client packages

2013-07-04 Thread Robert Collins
On 4 July 2013 04:19, Christopher Armstrong
chris.armstr...@rackspace.comwrote:

 On Tue, Jul 2, 2013 at 11:38 PM, Robert Collins
 robe...@robertcollins.net wrote:
  Radix points out I missed the naunce that you're targeting the users
  of python-novaclient, for instance, rather than python-novaclient's
  own tests.
 
 

...

  So it seems to me that a fast server fake can be used in tests of
  python-novaclient, *and* in tests of code using python-novaclient
  (including for instance, heat itself), and we get to write it just
  once per server, rather than once per server per language binding.
 
  -Rob


 I want to make sure I understond you. Let's say I have a program named
 cool-cloud-tool, and it uses python-novaclient, python-keystoneclient,
 and three other clients for OpenStack services. You're suggesting that
 its test suite should start up instances of all those OpenStack
 services with in-memory or otherwise localized backends, and
 communicate with them using standard python-*client functionality?


Yes.


 I can imagine that being a useful thing, if it's very easy to do, and
 won't increase my test execution time too much.


In bzr's test suite we found that such tests (using a non-encrypted plain
socket to talk to servers, rather than mock objects) was plenty fast:
slowness in the test suite occurred in tests that did a lot of actual vcs
operations - it's the lower layers that needed chopping out.

I think it's important to draw a distinction between what Joe Gordon is
suggesting and what I'm suggesting: nova operations are 10's to 100's of ms
today. I'm talking about a lightweight server that responds in single-digit
ms.

Consider a simple API call - say nova boot. Right now that has a good half
dozen rabbit RPC calls: API hands off work which is then done done
asynchronously: scheduler, neutron, compute, keystone once keypairs live
there, cinder and glance. It's a *lot* of work which isn't useful for
cool-cloud-tool, which just wants in it's test suite to:
 a) make a nova API call
 b) wait for the 'instance to boot'
 c) check that the expected API calls were made

a and b should be no more than a couple ms apart in a test server; (c) is
specific to a test server and not a use case the production server /should/
implement.

So while today the fake virt backend for nova exists, its still too far
down the stack to deliver the sort of story I'm talking about.

-Rob

-- 
Robert Collins rbtcoll...@hp.com
Distinguished Technologist
HP Cloud Services
___
OpenStack-dev mailing list
OpenStack-dev@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] Proposal for including fake implementations in python-client packages

2013-07-03 Thread Joe Gordon
On Mon, Jul 1, 2013 at 11:08 PM, Alex Gaynor alex.gay...@gmail.com wrote:

 Hi all,

 I suspect many of you don't know me as I've only started to get involved in
 OpenStack recently, I work at Rackspace and I'm pretty involved in other
 Python
 open source stuff, notably Django and PyPy, I also serve on the board of
 the
 PSF. So hiwave /!

 I'd like to propose an addition to all of the python-client libraries going
 forwards (and perhaps a requirement for future ones).

 What I'd like is for each client library, in addition to the actual
 implementation, is that they ship a fake, in-memory, version of the API.
 The
 fake implementations should take the same arguments, have the same return
 values, raise the same exceptions, and otherwise be identical, besides the
 fact
 that they are entirely in memory and never make network requests.

 Why not ``mock.Mock(spec=...)``:

 First, for those not familiar with the distinction between fakes and mocks
 (and
 doubles and stubs and ...): http://mumak.net/test-doubles/ is a great
 resource.
 https://www.youtube.com/watch?v=Xu5EhKVZdV8 is also a great resource which
 explains much of what I'm about to say, but better.

 Fakes are better than Mocks, for this because:

 * Mocks tend to be brittle because they're testing for the implementation,
 and
   not the interface.
 * Each mock tends to grow its own divergent behaviors, which tend to not be
   correct.

 http://stackoverflow.com/questions/8943022/reactor-stops-between-tests-when-using-twisted-trial-unittest/8947354#8947354
   explains how to avoid this with fakes
 * Mocks tend to encourage monkey patching, instead of just passing
 objects as
   parameters

 Again: https://www.youtube.com/watch?v=Xu5EhKVZdV8 is an amazing resource.


 This obviously adds a bit of a burden to development of client libraries,
 so
 there needs to be a good justification. Here are the advantages I see:



Just as  FYI, nova currently has a different way of addressing the two
points that a fake API server would address.




 * Helps flesh out the API: by having a simple implementation it helps in
   designing a good API.


Having a simple API implementation will not help us with having a good API,
as by the time its in code almost too late to change (the window to change
is between coded and released).  Instead a fake API would help validate
that the API follows the specs.  Nova has two ways of doing this now, unit
tests that exercise the APIs, and compare the results against recorded
output (see doc/api_samples/ in nova).  And we have tempest API tests.



 * Helps other projects tests: right now any project which uses an openstack
   client library has to do something manual in their tests, either add
 their
   own abstraction layer where they hand write an in-memory implementation,
 or
   they just monkey patch the socket, http, or client library to not make
   request. Either direction requires a bunch of work from each and every
   project using an openstack client. Having these in the core client
 libraries
   would allow downstream authors to simply swap out Connection classes.


Instead of a fake API server with no scheduler, no db etc, nova has a fake
backend.  So the only code path that is different then a real deployment is
which virt driver is used (https://review.openstack.org/#/c/24938/).



 I think these benefits out weigh the disadvantages. I'm not sure what the
 procedure for this is going forward. I think to demonstrate this concept it
 should start with a few (or even just one) client libraries, particularly
 ones
 which completely own the resources they serve (e.g. swift, marconi,
 ceilometer,
 trove), as compared to ones that interact more (e.g. neutrino, cinder, and
 nova). This is absolutely something I'm volunteering to work on, but I
 want to
 ensure this is an idea that has general buy in from the community and
 existing
 maintainers, so it doesn't wither.

 Thanks,
 Alex

 --
 I disapprove of what you say, but I will defend to the death your right
 to say it. -- Evelyn Beatrice Hall (summarizing Voltaire)
 The people's good is the highest law. -- Cicero
 GPG Key fingerprint: 125F 5C67 DFE9 4084

 ___
 OpenStack-dev mailing list
 OpenStack-dev@lists.openstack.org
 http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


___
OpenStack-dev mailing list
OpenStack-dev@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] Proposal for including fake implementations in python-client packages

2013-07-03 Thread Christopher Armstrong
On Tue, Jul 2, 2013 at 11:38 PM, Robert Collins
robe...@robertcollins.net wrote:
 Radix points out I missed the naunce that you're targeting the users
 of python-novaclient, for instance, rather than python-novaclient's
 own tests.


 On 3 July 2013 16:29, Robert Collins robe...@robertcollins.net wrote:

 What I'd like is for each client library, in addition to the actual
 implementation, is that they ship a fake, in-memory, version of the API. The
 fake implementations should take the same arguments, have the same return
 values, raise the same exceptions, and otherwise be identical, besides the
 fact
 that they are entirely in memory and never make network requests.

 So, +1 on shipping a fake reference copy of the API.

 -1 on shipping it in the client.

 The server that defines the API should have two implementations - the
 production one, and a testing fake. The server tests should exercise
 *both* code paths [e.g. using testscenarios] to ensure there is no
 skew between them.

 Then the client tests can be fast and efficient but not subject to
 implementation skew between fake and prod implementations.

 Back on Launchpad I designed a similar thing, but with language
 neutrality as a goal :
 https://dev.launchpad.net/ArchitectureGuide/ServicesRequirements#Test_fake

 And in fact, I think that that design would work well here, because we
 have multiple language bindings - Python, Ruby, PHP, Java, Go etc, and
 all of them will benefit from a low(ms or less)-latency test fake.

 So taking the aspect I missed into account I'm much happier with the
 idea of shipping a fake in the client, but... AFAICT many of our
 client behaviours are only well defined in the presence of a server
 anyhow.

 So it seems to me that a fast server fake can be used in tests of
 python-novaclient, *and* in tests of code using python-novaclient
 (including for instance, heat itself), and we get to write it just
 once per server, rather than once per server per language binding.

 -Rob


I want to make sure I understond you. Let's say I have a program named
cool-cloud-tool, and it uses python-novaclient, python-keystoneclient,
and three other clients for OpenStack services. You're suggesting that
its test suite should start up instances of all those OpenStack
services with in-memory or otherwise localized backends, and
communicate with them using standard python-*client functionality?

I can imagine that being a useful thing, if it's very easy to do, and
won't increase my test execution time too much.

-- 
IRC: radix
Christopher Armstrong
Rackspace

___
OpenStack-dev mailing list
OpenStack-dev@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev


Re: [openstack-dev] Proposal for including fake implementations in python-client packages

2013-07-02 Thread Christopher Armstrong
On Tue, Jul 2, 2013 at 11:10 AM, Kurt Griffiths
kurt.griffi...@rackspace.com wrote:
 The idea has merit; my main concern is that we would be duplicating
 significant chunks of code/logic between the fakes and the real services.

 How can we do this in a DRY way?


I've done it a few different ways for libraries I've worked on.

Usually, the fakes don't actually duplicate much code from the real
implementation. But in the cases they do, I've had situations like
this:


class RealImplementation(object):

  def do_network_stuff(self, stuff):
...

  def low_level_operation(self):
return self.do_network_stuff(GET /integer)

  def high_level_operation(self):
return self.low_level_operation() + 5


I'd just create a subclass like this:

class FakeImplementation(RealImplementation):

  def do_network_stuff(self, stuff):
raise NotImplementedError(This should never be called!)

  def low_level_operation(self):
return self.integer # or however you implement your fake


This has two interesting properties:

1. I don't have to reimplement the high_level_operation
2. If I forget to implement a fake version of some method that invokes
do_network_stuff, then it will blow up with a NotImplementedError so
my test doesn't accidentally do real network stuff.


This is just an example from some recent work I did on a simple RPC
client with an HTTP API (unrelated to OpenStack client libraries), but
that just so happens to be the case that Alex is discussing, so I
think it can work well.

--
IRC: radix
Christopher Armstrong
Rackspace

___
OpenStack-dev mailing list
OpenStack-dev@lists.openstack.org
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev