{"action":"created","issue":{"url":"https://api.github.com/repos/ganga-devs/ganga/issues/500","repository_url":"https://api.github.com/repos/ganga-devs/ganga","labels_url":"https://api.github.com/repos/ganga-devs/ganga/issues/500/labels{/name}","comments_url":"https://api.github.com/repos/ganga-devs/ganga/issues/500/comments","events_url":"https://api.github.com/repos/ganga-devs/ganga/issues/500/events","html_url":"https://github.com/ganga-devs/ganga/pull/500","id":155481942,"number":500,"title":"Use pytest features for running tests","user":{"login":"milliams","id":61316,"avatar_url":"https://avatars.githubusercontent.com/u/61316?v=3","gravatar_id":"","url":"https://api.github.com/users/milliams","html_url":"https://github.com/milliams","followers_url":"https://api.github.com/users/milliams/followers","following_url":"https://api.github.com/users/milliams/following{/other_user}","gists_url":"https://api.github.com/users/milliams/gists{/gist_id}","starred_url":"https://api.github.com/users/milliams/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/milliams/subscriptions","organizations_url":"https://api.github.com/users/milliams/orgs","repos_url":"https://api.github.com/users/milliams/repos","events_url":"https://api.github.com/users/milliams/events{/privacy}","received_events_url":"https://api.github.com/users/milliams/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ganga-devs/ganga/labels/Core","name":"Core","color":"d4c5f9"},{"url":"https://api.github.com/repos/ganga-devs/ganga/labels/enhancement","name":"enhancement","color":"009800"}],"state":"open","locked":false,"assignee":{"login":"milliams","id":61316,"avatar_url":"https://avatars.githubusercontent.com/u/61316?v=3","gravatar_id":"","url":"https://api.github.com/users/milliams","html_url":"https://github.com/milliams","followers_url":"https://api.github.com/users/milliams/followers","following_url":"https://api.github.com/users/milliams/following{/other_user}","gists_url":"https://api.github.com/users/milliams/gists{/gist_id}","starred_url":"https://api.github.com/users/milliams/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/milliams/subscriptions","organizations_url":"https://api.github.com/users/milliams/orgs","repos_url":"https://api.github.com/users/milliams/repos","events_url":"https://api.github.com/users/milliams/events{/privacy}","received_events_url":"https://api.github.com/users/milliams/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/ganga-devs/ganga/milestones/9","html_url":"https://github.com/ganga-devs/ganga/milestones/6.1.21","labels_url":"https://api.github.com/repos/ganga-devs/ganga/milestones/9/labels","id":1762322,"number":9,"title":"6.1.21","description":null,"creator":{"login":"rob-c","id":1102021,"avatar_url":"https://avatars.githubusercontent.com/u/1102021?v=3","gravatar_id":"","url":"https://api.github.com/users/rob-c","html_url":"https://github.com/rob-c","followers_url":"https://api.github.com/users/rob-c/followers","following_url":"https://api.github.com/users/rob-c/following{/other_user}","gists_url":"https://api.github.com/users/rob-c/gists{/gist_id}","starred_url":"https://api.github.com/users/rob-c/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rob-c/subscriptions","organizations_url":"https://api.github.com/users/rob-c/orgs","repos_url":"https://api.github.com/users/rob-c/repos","events_url":"https://api.github.com/users/rob-c/events{/privacy}","received_events_url":"https://api.github.com/users/rob-c/received_events","type":"User","site_admin":false},"open_issues":22,"closed_issues":0,"state":"open","created_at":"2016-05-12T12:39:16Z","updated_at":"2016-05-18T11:50:22Z","due_on":null,"closed_at":null},"comments":4,"created_at":"2016-05-18T11:50:22Z","updated_at":"2016-05-18T14:38:29Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ganga-devs/ganga/pulls/500","html_url":"https://github.com/ganga-devs/ganga/pull/500","diff_url":"https://github.com/ganga-devs/ganga/pull/500.diff","patch_url":"https://github.com/ganga-devs/ganga/pull/500.patch"},"body":"This PR introduces the use of pytest fixtures as a way of setting up tests. pytest fixtures are an alternative to `unittest.TestCase`-style classes that offer more flexibility and composability. If you're not familiar with them I suggest giving [this post from pythontesting.net](http://pythontesting.net/framework/pytest/pytest-fixtures-nuts-bolts/) a read and following some of the links at the beginning of that post.\r\n\r\nThe gist of it is that:\r\n```python\r\ndef test_job_create(gpi):\r\n    j = gpi.Job()\r\n    assert j.id == 0\r\n```\r\nis a full working test module. Alternatively this can be written as:\r\n```python\r\ndef test_job_create(gpi):\r\n    from Ganga.GPI import Job\r\n    j = Job()\r\n    assert j.id == 0\r\n```\r\nor\r\n```python\r\n@pytest.mark.usefixtures('gpi')\r\ndef test_job_create():\r\n    from Ganga.GPI import Job\r\n    j = Job()\r\n    assert j.id == 0\r\n```\r\n\r\nBehind the scenes this is calling the same `start_ganga()` and `stop_ganga()` functions that `GangaUnitTest` is currently using. Overall I have seen a definite speed improvement with these fixtures (up to 10%), especially on the smaller tests where a lot of time was being spent with the `unittest` boilerplate.\r\n\r\nThis also introduces an `@add_config()` decorator for these test function which is used like\r\n```python\r\n@add_config([('Configuration', 'user', 'test')])\r\ndef test_add_config(gpi):\r\n    assert gpi.config['Configuration'].user == 'test'\r\n```\r\n\r\nThis does not remove the current `GangaUnitTest` class so that can still be used."},"comment":{"url":"https://api.github.com/repos/ganga-devs/ganga/issues/comments/220046866","html_url":"https://github.com/ganga-devs/ganga/pull/500#issuecomment-220046866","issue_url":"https://api.github.com/repos/ganga-devs/ganga/issues/500","id":220046866,"user":{"login":"milliams","id":61316,"avatar_url":"https://avatars.githubusercontent.com/u/61316?v=3","gravatar_id":"","url":"https://api.github.com/users/milliams","html_url":"https://github.com/milliams","followers_url":"https://api.github.com/users/milliams/followers","following_url":"https://api.github.com/users/milliams/following{/other_user}","gists_url":"https://api.github.com/users/milliams/gists{/gist_id}","starred_url":"https://api.github.com/users/milliams/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/milliams/subscriptions","organizations_url":"https://api.github.com/users/milliams/orgs","repos_url":"https://api.github.com/users/milliams/repos","events_url":"https://api.github.com/users/milliams/events{/privacy}","received_events_url":"https://api.github.com/users/milliams/received_events","type":"User","site_admin":false},"created_at":"2016-05-18T14:38:29Z","updated_at":"2016-05-18T14:38:29Z","body":"The problem with the magic is that it makes these test functions drift further away from being 'the Python programming language' and instead 'the Ganga programming language'. Using any IDE or static analysis tool will see `Job` and will have no idea where that name is defined.\r\n\r\nI'd like to be moving towards a more Pythonic world where we are using little-`ganga` more so that we can do things exactly as we would in a little-`ganga` script like:\r\n```python\r\nimport ganga\r\nganga.start_monitoring()\r\nj = ganga.Job()\r\nj.submit()\r\nsleep(10)\r\nassert j.status == 'completed'\r\n```\r\nwhich, with some appropriately written fixtures, could become:\r\n```python\r\n@pytest.mark.usefixtures('monitoring')\r\ndef test_little_ganga():\r\n    import ganga\r\n    j = ganga.Job()\r\n    j.submit()\r\n    sleep(10)\r\n    assert j.status == 'completed'\r\n```\r\nThe alternative is moving towards a system more like the old `foo.gpi` files and we write a runner for pytest which finds `*.gpi` files and runs then within the `gpi` fixture."}}