[discuss] Organization purge tests with ckanapi client

@tobes @wardi

For discussion, this is a version of pull request <https://github.com/okfn/ckan/pull/707> (group and organization purging) with the [organization_purge functional tests](https://github.com/okfn/ckan/blob/organization-purge-tests-with-ckanapi-client/ckan/tests/functional/api/model/test_organization.py) done using [ckanapi](https://github.com/open-data/ckanapi) instead (you can ignore the rest of this pull request, and just look at those tests).

I'm actually using a modified ckanapi, I made some tweaks to make it more convenient for these tests, I'll send some pull requests to ckanapi

I don't like how I have to do ``self.api.action.`` every time, that's too long:

* Can ckanapi be changed to enable e.g. ``self.api.user_list()``? (i.e. without the `.action`)

* Or maybe test classes like ``TestOrganizationPurging`` should inherit from
     ``ckanapi.TestAppCKAN``, then they could do ``self.action.user_list()`` or even ``self.user_list()``?

I'm passing ``apikey=self.sysadmin.apikey`` every time because I like it to be explicit when I'm calling an action as a sysadmin, but I could have just initialized ``self.api`` with the apikey in the first place, then I wouldn't have to pass it each time.

Things get awkward at some points, but I think this is because the CKAN API is awkard and should be fixed to be nicer to use (although that would mean breaking the API and we may have to do v4):

* When creating or updating a group or org, you can't give its users and datasets as simple lists of user and dataset names, you have to give lists of dicts that are a pain to construct

* When doing group_show or organization_show, you don't get the users and datasets as simple lists of names but as lists of dicts again (makes for long, awkward asserts, when it should just be ``assert user_name not in organization['members']``)

* Also when doing user_show or package_show, the groups and orgs are not simple lists of names but lists of dicts again. In some cases though, you do just get names.

* Exceptions raised are inconsistent, the exception object either has a dict as ``.extra_msg``, or a string as ``.extra_msg``, or a dict as ``.error_dict``, etc.