{"action":"created","issue":{"url":"https://api.github.com/repos/sindresorhus/ava/issues/222","labels_url":"https://api.github.com/repos/sindresorhus/ava/issues/222/labels{/name}","comments_url":"https://api.github.com/repos/sindresorhus/ava/issues/222/comments","events_url":"https://api.github.com/repos/sindresorhus/ava/issues/222/events","html_url":"https://github.com/sindresorhus/ava/issues/222","id":117149842,"number":222,"title":"Support nested groups?","user":{"login":"novemberborn","id":33538,"avatar_url":"https://avatars.githubusercontent.com/u/33538?v=3","gravatar_id":"","url":"https://api.github.com/users/novemberborn","html_url":"https://github.com/novemberborn","followers_url":"https://api.github.com/users/novemberborn/followers","following_url":"https://api.github.com/users/novemberborn/following{/other_user}","gists_url":"https://api.github.com/users/novemberborn/gists{/gist_id}","starred_url":"https://api.github.com/users/novemberborn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/novemberborn/subscriptions","organizations_url":"https://api.github.com/users/novemberborn/orgs","repos_url":"https://api.github.com/users/novemberborn/repos","events_url":"https://api.github.com/users/novemberborn/events{/privacy}","received_events_url":"https://api.github.com/users/novemberborn/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/sindresorhus/ava/labels/enhancement","name":"enhancement","color":"84b6eb"},{"url":"https://api.github.com/repos/sindresorhus/ava/labels/question","name":"question","color":"cc317c"}],"state":"open","locked":false,"assignee":{"login":"jamestalmage","id":4082216,"avatar_url":"https://avatars.githubusercontent.com/u/4082216?v=3","gravatar_id":"","url":"https://api.github.com/users/jamestalmage","html_url":"https://github.com/jamestalmage","followers_url":"https://api.github.com/users/jamestalmage/followers","following_url":"https://api.github.com/users/jamestalmage/following{/other_user}","gists_url":"https://api.github.com/users/jamestalmage/gists{/gist_id}","starred_url":"https://api.github.com/users/jamestalmage/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamestalmage/subscriptions","organizations_url":"https://api.github.com/users/jamestalmage/orgs","repos_url":"https://api.github.com/users/jamestalmage/repos","events_url":"https://api.github.com/users/jamestalmage/events{/privacy}","received_events_url":"https://api.github.com/users/jamestalmage/received_events","type":"User","site_admin":false},"milestone":null,"comments":26,"created_at":"2015-11-16T15:32:56Z","updated_at":"2016-01-25T22:44:32Z","closed_at":null,"body":"Currently the test files support a flat list of tests, each sharing all `before` , `beforeEach`, `afterEach` & `after` hooks. I find it useful to declare nested groups with their own hooks, while inheriting context from the parent.\r\n\r\nFor example I'm stubbing promise behavior and need to write test for if the promise is fulfilled or if it's rejected. Ideally I could do something like:\r\n\r\n```js\r\ntest.beforeEach(t => {\r\n  t.context.behavior = sinon.stub({ getPromise () })\r\n  // Return a pending promise\r\n  t.context.behavior.getPromise.returns(new Promise(() => {}))\r\n})\r\n\r\n// Add optional title\r\ntest.group('promise is fulfilled', () => {\r\n  test.beforeEach(t => {\r\n    t.context.behavior.getPromise.returns(Promise.resolve(true))\r\n  })\r\n\r\n  test(async () => {\r\n    const value = await t.context.behavior.getPromise()\r\n    t.true(value)\r\n  })\r\n})\r\n\r\ntest.group('promise is rejected', () => {\r\n  // You get the idea…\r\n})\r\n```\r\n\r\nEach group would maintain its own list of hooks. Hooks could be inherited from the parent group at runtime or when initializing. There would be a root group for the test file itself.\r\n\r\nThis would allow building alternative test interfaces alongside AVA.\r\n\r\nI'd be happy to try and do a PR for this if there's interest.\r\n\r\n---\r\n\r\nP.S. AVA looks really intriguing! Test runners could do with some shaking up :+1: "},"comment":{"url":"https://api.github.com/repos/sindresorhus/ava/issues/comments/174707342","html_url":"https://github.com/sindresorhus/ava/issues/222#issuecomment-174707342","issue_url":"https://api.github.com/repos/sindresorhus/ava/issues/222","id":174707342,"user":{"login":"BarryThePenguin","id":1351912,"avatar_url":"https://avatars.githubusercontent.com/u/1351912?v=3","gravatar_id":"","url":"https://api.github.com/users/BarryThePenguin","html_url":"https://github.com/BarryThePenguin","followers_url":"https://api.github.com/users/BarryThePenguin/followers","following_url":"https://api.github.com/users/BarryThePenguin/following{/other_user}","gists_url":"https://api.github.com/users/BarryThePenguin/gists{/gist_id}","starred_url":"https://api.github.com/users/BarryThePenguin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BarryThePenguin/subscriptions","organizations_url":"https://api.github.com/users/BarryThePenguin/orgs","repos_url":"https://api.github.com/users/BarryThePenguin/repos","events_url":"https://api.github.com/users/BarryThePenguin/events{/privacy}","received_events_url":"https://api.github.com/users/BarryThePenguin/received_events","type":"User","site_admin":false},"created_at":"2016-01-25T22:44:32Z","updated_at":"2016-01-25T22:44:32Z","body":"My current day job is working with one team on a larger angular app written by multiple teams. We test with karma and jasmine. Our component classes (controllers and services) have a history of being larger than necessary. Our team is trying to reduce the size and complexity of our new components. It's also our first attempt at any kind of TDD/BDD, so we are learning a lot.\r\n\r\nOur application structure boils down to (with 30+ components):\r\n\r\n```\r\napp/\r\n- componentA/\r\n - componentA.js\r\n - componentA.html\r\n - componentA.Test.js\r\n - componentA.Ctrl.js\r\n - componentA.Ctrl.Test.js\r\n - componentA.Svc.js\r\n - componentA.Svc.Test.js\r\n- componentB/...\r\n- ...\r\n- componentZ/...\r\n```\r\n\r\nSo that's currently 3 test files already per component.\r\n\r\nWe structuring tests is to describe what is being tested, then describe each instance method with both a pass and fail test plus any other extra cases that need to be covered.\r\n\r\nTest structure follows something similar to:\r\n\r\n```javascript\r\ndescribe('Component A Controller', function() {\r\n  beforeEach(...)\r\n  \r\n  describe('instanceMethod1', function() {\r\n    it('should have a happy path', function() {\r\n    })\r\n    it('should have a sad path', function() {\r\n    })\r\n    it('should meet a range of user story requirements', function() {\r\n    })\r\n  })\r\n\r\n  describe('instanceMethod2', ...)\r\n\r\n  describe('instanceMethodN', ...)\r\n})\r\n```\r\n\r\nOne benefit of this method is we get nice mapping of tests to user stories with a clear report for the broader team to view (BA's, managers, test team etc). The output of the report reads like:\r\n\r\nComponent A Controller instanceMethod1 should reach some desired outcome\r\n\r\nThere's probably a lot of thing here that could be improved/structured differently. That's my experiance"}}