Skip to content

Commit

Permalink
Fix documentation problems.
Browse files Browse the repository at this point in the history
  • Loading branch information
huseyinyilmaz committed Aug 19, 2016
1 parent ea1a447 commit 8b02097
Showing 1 changed file with 29 additions and 26 deletions.
55 changes: 29 additions & 26 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ First we create a placebo object for that endpoint.
'title': 'The Matrix'}
After having all the data in place, we can use our placebo to decorate our test functions like this.
After having all the data in place, we can use our placebo to decorate our test methods like this.

.. code-block:: python
Expand All @@ -152,7 +152,7 @@ After having all the data in place, we can use our placebo to decorate our test
In first method, we directly used the placebo object. In the second method we changed the status of the object to 500 and tested the error case. Notice how logic for mocking the endpoint and test is seperated. We also reused same object for testing the valid response and error case.

As a matter of fact, Placebo object is not only useful for testing. Since main interface is a decorator pattern, you can use it on any function you want, like views in your web application. That way you can develop your applications against mock data or simulate error cases on your development environment very easily.
As a matter of fact, Placebo object is not only useful for testing. Since main interface is a decorator pattern, you can use it on any callable you want, like views in your web application. That way you can develop your applications against mock data or simulate error cases on your development environment very easily.


Installation
Expand Down Expand Up @@ -192,7 +192,7 @@ Basic usage of placebo can be as follows:
url = 'http://www.acme.com/items/'
body = '[{"id": 1}, {"id": 2}, {"id": 3}]'
When we decorate a function with this placebo class, every 'GET' request to http://www.acme.com/items/ url will return 200 response with following body '[{"id": 1}, {"id": 2}, {"id": 3}]'.
When we decorate a callable with this placebo class, every 'GET' request to http://www.acme.com/items/ url will return 200 response with following body '[{"id": 1}, {"id": 2}, {"id": 3}]'.

We can use this placebo in following test:

Expand Down Expand Up @@ -263,12 +263,12 @@ A placebo class can have following properties.

5) *headers*: If mock is applied headers will be used as http headers. Type of headers should be dictionary. (Keys should be header names and values should be header values, both strings.)

6) *backend*: Backends provide actual functionality of placebo. Currently there are two different backends that are supported by default -- httpretty and httmock. By default httmock is tried. If it cannot be imported, httpretty is tried. Backend is basically a function that gets a placebo object as argument and mocks the current apis.
6) *backend*: Backends provide actual functionality of placebo. Currently there are two different backends that are supported by default -- httpretty and httmock. By default httmock is tried. If it cannot be imported, httpretty is tried. Backend is basically a callable that gets a placebo object as argument and returns a decorator that mocks the current apis.

Dynamic placebo classes
-----------------------

Previous pacebo class has static properties with already defined values. Most of the properties of placebo object can also be defined as methods therefore values can be calculated on the fly. Here is an example placebo objects that returns a mock response with id it receives. If id is not an integer, it returns 404 response. Even though those kind of placebo objects are not suitable for tests, they are very usefull for development.
Previous pacebo class has static properties with already defined values. Most of the properties of placebo object can also be defined as methods therefore values can be calculated on the fly. Here is an example placebo object that returns a mock response with id it receives. If id is not an integer, it returns 404 response. Even though those kind of placebo objects are not suitable for tests, they are very usefull for development.


.. code-block:: python
Expand Down Expand Up @@ -315,7 +315,7 @@ Previous pacebo class has static properties with already defined values. Most of
status = 404
return status
As seen in the example, almost all the properties of the Placebo object can be written as methods. Some properties are evaluated for each request therefore ($FIXME$) receives url, headers, body. Rest of the properties are evaluated only once on initialization therefore does not receive any extra information about the request. Only property that cannot be implemented as method is ``backend``. The reason for that is ``backend`` is of type function so we cannot distinguish backends from methods that return backends.
As seen in the example, almost all the properties of the Placebo object can be written as callables. When we implement those attributes as callables, it might be important to know when those methods are invoked. Some are evaluated for each request, therefore receives request specific informations like url, headers, body. Those attributes are body, headers and status. Rest of the properties are evaluated only once when we apply the decorator (usually on initialization) therefore they do not receive any extra information about the request. Those attributes are url and method. Only property that cannot be implemented as method is ``backend``. The reason for that is ``backend`` is of type callable, so we cannot distinguish backends from callables that return backends. Another way to think about this is some attributes are used to filter requests. So they do not receive any request information. Other are used to form a response.Those attributes gets request information to create their mock responses.

Placebo properties
------------------
Expand All @@ -324,29 +324,29 @@ This section aims to describe each placebo property in detail.

- *url* : url is used to decide whether current placebo needs to be applied on current request. This property is used only once during initialization time. It can have ``str``, ``unicode``, ``urlparse.ParseResult`` or ``urlparse.SplitResult`` as type. ``str`` can also be set to a method that returns values of one of the types listed above.

- *method*: method is also used to decide whether current placebo needs to be applied on current request. It is used only once during initialization. It can have ``str`` or ``unicode`` types. It can contain one of following values: 'GET', 'POST', 'PUT', 'DELETE',..etc.. Alternatively, ``method`` can be set to a function that returns one of the values above.
- *method*: method is also used to decide whether current placebo needs to be applied on current request. It is used only once during initialization. It can have ``str`` or ``unicode`` types. It can contain one of following values: 'GET', 'POST', 'PUT', 'DELETE',..etc.. Alternatively, ``method`` can be set to a callable that returns one of the value types above.

- *status*: Status represents http status of response. If placebo is matched with current request, a mock response for that request will be created with the status code of this attribute. This attribute needs to be of type ``int`` with values like 200, 203, 400, 404, 500, 503 etc. This attribute can also be set to a function. Since this attribute is used to create a response, this function will need to get 3 additional attributes that describes the request. Those arguments are request_url, request_header and request_body. (See examples about usage above.)
- *status*: Status represents http status of response. If placebo is matched with current request, a mock response for that request will be created with the status code of this attribute. This attribute needs to be of type ``int`` with values like 200, 203, 400, 404, 500, 503 etc. This attribute can also be set to a callable. Since this attribute is used to create a response, this callable will need to get 3 additional attributes that describes the request. Those arguments are request_url, request_header and request_body. (See examples above.)

- *body*: This attribute is used to create the body of the response. It should be of type ``str` or ``unicode``. It can also be set to a function which will be called for every request. This function needs to accept request_url, request_header, request_body arguments.
- *body*: This attribute is used to create the body of the response. It should be of type ``str` or ``unicode``. It can also be set to a callable which will be called for every request. This callable needs to accept request_url, request_header, request_body arguments.

- *headers*: This attribute is used to create the header of the response. It should be of type ``dict`` (keys are header names and values are header values, both strings)

- *backend*: This is a meta attribute instead of a filter or response attribute. It is the backend that ``Placebo`` object will use to create mock objects. Currently there are 2 backends: ``backends.httpprettybackend.get_decorator`` and ``placebo.backends.httmockbackend.get_decorator``. Unlike all the other attributes, ``backend`` attribute cannot be set to a function that returns backends, just to the backed itself, which is a function as well. It needs to get a Placebo instance as argument and return a decorator that applies that placebo object. More explanation can be found in the "Implementing backends" section.)
- *backend*: This is a meta attribute instead of a filter or response attribute. It is the backend that ``Placebo`` object will use to create mock objects. Currently there are 2 backends: ``backends.httpprettybackend.get_decorator`` and ``placebo.backends.httmockbackend.get_decorator``. Unlike all the other attributes, ``backend`` attribute cannot be set to a callable that returns backends. It needs to get a Placebo instance as argument and return a decorator that applies that placebo object. More explanation can be found in the "Implementing backends" section.)

Using placebo classes as decorator
==================================

Interface for a placebo class is a decorator. To use a placebo class, decorate method of
class is used to decorate a function.
class is used to decorate a callable.

.. code-block:: python
@SimplePlacebo.decorate
def function_to_mock(arg1, arg2):
...
Placebo decorator can also accepts attributes. All placebo attributes explains above as argument.
Placebo decorator can also accepts attributes. All placebo attributes explained above can be provided as an argument to decorator method.

.. code-block:: python
Expand Down Expand Up @@ -374,7 +374,7 @@ Placebo decorator can accept following arguments:
Getting a placebo instance
==========================
In the placebo interface, Placebo class is used to decorate functions. When we decorate a function with a placebo class, an object for that class is instantiated and used to decorate current function. So each decorated function gets its own object to hold its mock information. Because object instantiation is handled by Placebo, there is no direct access to actual instance for each funciton. But for some edge cases,there is a need to access placebo objects. In those cases arg_name attribute of decorator can be used. If arg_name argument is specified current Placebo instance will be passed to decorated function as a keyword argument with given name. See "Accessing the last mocked request" section for a usecase.
In the placebo interface, Placebo class is used to decorate callables. When we decorate a callable with a placebo class, an object for that class is instantiated and used to decorate current callable. So each decorated callable gets its own placebo instance to hold its mock information. Because object instantiation is handled by Placebo, there is no direct access to actual instance for each callable. But for some edge cases,there is a need to access placebo instances. In those cases arg_name attribute of decorator can be used. If arg_name argument is specified current Placebo instance will be passed to decorated callable as a keyword argument with given name. See "Accessing the last mocked request" section for a usecase.
.. code-block:: python
Expand All @@ -385,7 +385,7 @@ In the placebo interface, Placebo class is used to decorate functions. When we d
Accessing the last mocked request
=================================
Some times, we might want to access the last mocked request. There are 2 ways to do this: The easiest is to access last request from the class.
Some times, we might want to access the last mocked request. There are 2 ways to do this: The easiest way is to access last request from the class.
.. code-block:: python
Expand Down Expand Up @@ -415,11 +415,11 @@ Some times, we might want to access the last mocked request. There are 2 ways to
request_query_params = last_request.query
...
Accesing the placebo object through the class like this is really easy and does not require any change on rest of the code (`last_request = SimplePlacebo.last_request`). But there is a downside to this aproach: Since last_request here is a class attribute, it is shared by all instances. So, if get_items call fails to do a request, we can still have a last_request attribute on class becuase another test might be using same Placebo object and could already have registered a ``last_request`` before our test is run.
Accesing the placebo object through the class like this is really easy and does not require any change on rest of the code (`last_request = SimplePlacebo.last_request`). But there is a downside to this aproach: Since last_request here is a class attribute, it is shared by all instances. So, if get_items call fails to do a request, we can still have a last_request attribute on class becuase another test might be using same Placebo class and could already have registered a ``last_request`` before our test is run.
To solve this problem, you can use the second way of getting the last mocked request -- By accessing the ``last_requet`` attribute of a Placebo instance. That way you can access the ``last_request`` that is only mocked by the current instance.
To get ``last_request`` from an instance, first we need access the instance of Placebo we want to use. Here is an example:
To get ``last_request`` from an instance, first we need to access the instance of Placebo we want to use. Here is an example:
.. code-block:: python
Expand Down Expand Up @@ -468,12 +468,12 @@ Mocking with regex url
For some cases, we might want to mock a url using a regular expression.
Unfortunately each backend has its own way of implementing regular expressions and implementations are incompatible with others. For that reason there is no generic way of describing regex urls. In placebo, we choose to delegate regex urls to backends. So each backends has its own version of regex implementation.
Unfortunately each backend has its own way of implementing regular expressions and implementations are incompatible with each other. For that reason, there is no generic way of describing regex urls. In placebo, we choose to delegate regex urls to backends. So each backends has its own version of regex support.
Regex url in httmock backend
----------------------------
Regex urls in httmock backend
-----------------------------
Httmock requires url attribute to be of type ``urlparse.ParseResult`` or ``urlparse.SplitResult`` to use backends. If the ``url`` attribute is in string type of regex ($FIXME$), mock will not work.
To use regex url with Httmock, url attribute must be type of ``urlparse.ParseResult`` or ``urlparse.SplitResult``. If the ``url`` attribute is ``str``, ``unicode`` type or a compiled ``regex`` instance, regex mock will not work. Here is an example placebo with regex url:
.. code-block:: python
Expand All @@ -491,14 +491,14 @@ Httmock requires url attribute to be of type ``urlparse.ParseResult`` or ``urlpa
...
In this placebo object we are we are mocking all urls with format "http://www.acme.com/items/<item_id>/"
In this placebo object, we are we are mocking all urls with format "http://www.acme.com/items/<item_id>/"
(See `tests/placebo_tests.py` file or `examples/` directory for different examples.)
Regex url in httpretty backend
------------------------------
Regex urls in httpretty backend
-------------------------------
Httpretty backend, requires url attribute to be of type regex pattern. If regex url is of type ``urlparse.ParseResult`` or ``urlparse.SplitResult``, regex will not work. Here is an example url for httpretty.
Httpretty backend, requires url attribute to be a compiled regex pattern instance. If regex url is of type ``urlparse.ParseResult`` or ``urlparse.SplitResult``, regex will not work. Here is an example url for httpretty.
.. code-block:: python
Expand All @@ -511,6 +511,9 @@ Httpretty backend, requires url attribute to be of type regex pattern. If regex
(See `tests/placebo_tests.py` file or `examples/` directory for different examples.)
To summarize, httmock requires regex url to be a ParseResult instance. httpretty on the other hand, requires url attribute to be a compiled regex instance.
Backends
========
Expand All @@ -525,7 +528,7 @@ If both libraries are installed and we want to use a non-default backend, the ba
Implementing a custom backend
-----------------------------
A backend is a function that accepts a placebo instance as an arguments and returns a decorator. Placebo object has special methods for backends to consume placebo data. Those methods are:
A backend is a callable that accepts a placebo instance as an argument and returns a decorator. Placebo object has special methods for backends to consume placebo data. Those methods are:
.. code-block:: python
Expand All @@ -541,7 +544,7 @@ A backend is a function that accepts a placebo instance as an arguments and retu
def _get_headers(self, url, headers, body):
...
From those functions, _get_url and _get_method can be invoked on decorator initialization. But rest of the methods must be called for each request. Therefore, they can only be invoked from inside the decorator. (See `placebo/backends/` directory for example implementations.)
From those methods, _get_url and _get_method can be invoked on decorator initialization. But rest of the methods must be called for each request. Therefore, they can only be invoked from inside the decorator. (See `placebo/backends/` directory for example implementations.)
Caveats
=======
Expand Down

0 comments on commit 8b02097

Please sign in to comment.