Skip to content

Commit 921a158

Browse files
committed
Add subsetting to Karma runner
1 parent 69a6e3c commit 921a158

File tree

6 files changed

+203
-34
lines changed

6 files changed

+203
-34
lines changed

launchable/commands/subset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ def get_payload(
529529

530530
def _collect_potential_test_files(self):
531531
LOOSE_TEST_FILE_PATTERN = r'(\.(test|spec)\.|_test\.|Test\.|Spec\.|test/|tests/|__tests__/|src/test/)'
532-
EXCLUDE_PATTERN = r'(BUILD|Makefile|Dockerfile|LICENSE|.gitignore|.gitkeep|.keep|id_rsa|rsa|blank|taglib)|\.(xml|json|jsonl|txt|yml|yaml|toml|md|png|jpg|jpeg|gif|svg|sql|html|css|graphql|proto|gz|zip|rz|bzl|conf|config|snap|pem|crt|key|lock|jpi|hpi|jelly|properties|jar|ini|mod|sum|bmp|env|envrc|sh)$' ## noqa E501
532+
EXCLUDE_PATTERN = r'(BUILD|Makefile|Dockerfile|LICENSE|.gitignore|.gitkeep|.keep|id_rsa|rsa|blank|taglib)|\.(xml|json|jsonl|txt|yml|yaml|toml|md|png|jpg|jpeg|gif|svg|sql|html|css|graphql|proto|gz|zip|rz|bzl|conf|config|snap|pem|crt|key|lock|jpi|hpi|jelly|properties|jar|ini|mod|sum|bmp|env|envrc|sh)$' # noqa E501
533533

534534
try:
535535
git_managed_files = subprocess.run(['git', 'ls-files'], stdout=subprocess.PIPE,

launchable/test_runners/karma.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# This runner only supports recording tests
2-
# For subsetting, use 'ng' test runner instead
3-
# It's possible to use 'karma' runner for recording, and 'ng' runner for subsetting, for the same test session
41
import json
52
from typing import Dict, Generator, List
63

@@ -34,6 +31,30 @@ def record_tests(client, reports):
3431
client.run()
3532

3633

34+
@click.option('--with', 'output_format', type=str, default=None,
35+
help='Format output for specific test runner (e.g., "ng" for Angular CLI)')
36+
@launchable.subset
37+
def subset(client, output_format):
38+
"""
39+
Usage:
40+
find src -name "*.spec.ts" -o -name "*.spec.js" > test-list.txt
41+
cat test-list.txt | launchable subset --target 10% karma
42+
43+
# Output in ng test format
44+
find src -name "*.spec.ts" | launchable subset --target 10% karma --with ng
45+
"""
46+
for t in client.stdin():
47+
path = t.strip()
48+
if path:
49+
client.test_path(path)
50+
51+
if output_format == 'ng':
52+
client.formatter = lambda x: "--include={}".format(x[0]['name'])
53+
client.separator = " "
54+
55+
client.run()
56+
57+
3758
class JSONReportParser:
3859
"""
3960
Sample Karma report format:

tests/data/karma/README.md

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
Karma
2+
======
3+
4+
### Karma Project
5+
6+
**Create project:**
7+
8+
```bash
9+
npm init -y
10+
npm install --save-dev karma karma-jasmine jasmine-core karma-chrome-launcher karma-json-reporter
11+
```
12+
The instructions are based on:
13+
https://karma-runner.github.io/6.4/intro/installation.html
14+
15+
**Generate `karma.conf.js`:**
16+
```bash
17+
npx karma init
18+
19+
# Answer the prompts:
20+
# - Framework: jasmine
21+
# - Require.js: no
22+
# - Browser: ChromeHeadless
23+
# - Test files:
24+
# - Files to exclude:
25+
# - Watch files: no
26+
```
27+
28+
**Add following to `karma.conf.js` while keeping the current settings:**
29+
```
30+
module.exports = function (config) {
31+
config.set({
32+
files: process.env.KARMA_FILES ? JSON.parse(process.env.KARMA_FILES) : [],
33+
...
34+
plugins: [
35+
...
36+
require('karma-json-reporter')
37+
],
38+
jsonReporter: {
39+
outputFile: require('path').join(__dirname, 'test-results.json'),
40+
stdout: false
41+
},
42+
reporters: [..., 'json']
43+
});
44+
};
45+
```
46+
47+
**Create a test file:**
48+
```bash
49+
mkdir test
50+
51+
cat > test/example.spec.js << 'EOF'
52+
describe('Example', function() {
53+
it('should pass', function() {
54+
expect(true).toBe(true);
55+
});
56+
57+
it('should add numbers', function() {
58+
expect(1 + 1).toBe(2);
59+
});
60+
});
61+
EOF
62+
```
63+
64+
**Record session:**
65+
```bash
66+
git add . && git commit -m "Initial commit"
67+
launchable record build --name ${BUILD_NAME}
68+
launchable record session --build ${BUILD_NAME} > session.txt
69+
```
70+
71+
**Run all tests:**
72+
```bash
73+
find test -name "*.spec.ts" -o -name "*.spec.js" > test_list.txt
74+
cat test_list.txt
75+
KARMA_FILES=$(cat test_list.txt | jq -R -s -c 'split("\n")[:-1]')
76+
npx karma start --single-run
77+
```
78+
79+
**Record tests:**
80+
```bash
81+
launchable record tests karma test-results.json
82+
```
83+
84+
**Request subset:**
85+
```bash
86+
cat test_list.txt | launchable subset --target 25% karma > subset.txt
87+
```
88+
89+
**Run subset of tests:**
90+
```bash
91+
KARMA_FILES=$(cat subset.txt | jq -R -s -c 'split("\n")[:-1]')
92+
npx karma start --single-run
93+
```
94+
95+
### Angular Project with Karma
96+
97+
**Create project:**
98+
99+
```
100+
ng new ng-karma-app --test-runner=karma
101+
cd ng-karma-app
102+
npm install --save-dev karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter jasmine-core karma-json-reporter @types/jasmine
103+
ng test --no-watch --no-progress --browsers=ChromeHeadless
104+
```
105+
106+
The instructions are based on:
107+
- https://angular.dev/guide/testing/karma
108+
- https://www.npmjs.com/package/karma-json-reporter
109+
110+
**Generate `karma.conf.js`:**
111+
```
112+
ng generate config karma
113+
```
114+
115+
**Add following to `karma.conf.js` while keeping the current settings:**
116+
```
117+
module.exports = function (config) {
118+
config.set({
119+
...
120+
plugins: [
121+
...
122+
require('karma-json-reporter')
123+
],
124+
jsonReporter: {
125+
outputFile: require('path').join(__dirname, 'test-results.json'),
126+
stdout: false
127+
},
128+
reporters: [..., 'json']
129+
});
130+
};
131+
```
132+
133+
**Record session:**
134+
```
135+
git add . && git commit -m "Initial commit"
136+
launchable record build --name ${BUILD_NAME}
137+
launchable record session --build ${BUILD_NAME} > session.txt
138+
```
139+
140+
**Record tests:**
141+
```
142+
ng test --no-watch --no-progress --browsers=ChromeHeadless
143+
launchable record tests karma test-results.json
144+
```
145+
146+
**Subset tests with **ng**:**
147+
```
148+
ng test --list-tests | grep src > test_list.txt
149+
cat test_list.txt | launchable subset --target 25% karma --with ng > subset.txt
150+
```
151+
152+
**Run subset of tests**
153+
```
154+
ng test --no-watch --no-progress --browsers=ChromeHeadless --include $(cat subset.txt)
155+
```
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
{ "type": "file", "name": "foo/bar/zot.spec.ts" }
55
],
66
[
7-
{ "type": "file", "name": "client-source/src/app/shared/other-test.spec.ts" }
7+
{ "type": "file", "name": "foo/bar/another.spec.ts" }
88
]
99
],
10-
"testRunner": "ng",
10+
"testRunner": "karma",
1111
"goal": {"type": "subset-by-percentage", "percentage": 0.1},
1212
"ignoreNewTests": false,
1313
"session": { "id": "16" },
1414
"getTestsFromGuess": false,
1515
"getTestsFromPreviousSessions": false
16-
}
16+
}

tests/test_runners/test_karma.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,27 @@ def test_record_tests_json(self):
1919
self.assert_record_tests_payload('record_test_result.json')
2020

2121
@responses.activate
22-
@mock.patch.dict(os.environ, {"LAUNCHABLE_TOKEN": CliTestCase.launchable_token})
22+
@mock.patch.dict(os.environ,
23+
{"LAUNCHABLE_TOKEN": CliTestCase.launchable_token})
2324
def test_subset(self):
24-
# emulate launchable record build
2525
write_build(self.build_name)
2626

27-
result = self.cli('subset', '--target', '10%', '--base',
28-
os.getcwd(), 'karma', '--with', 'ng', input="a.ts\nb.ts")
27+
subset_input = """foo/bar/zot.spec.ts
28+
foo/bar/another.spec.ts
29+
"""
30+
result = self.cli('subset', '--target', '10%', 'karma', input=subset_input)
31+
self.assert_success(result)
32+
self.assert_subset_payload('subset_payload.json')
33+
34+
@responses.activate
35+
@mock.patch.dict(os.environ,
36+
{"LAUNCHABLE_TOKEN": CliTestCase.launchable_token})
37+
def test_subset_with_ng(self):
38+
write_build(self.build_name)
39+
40+
subset_input = """foo/bar/zot.spec.ts
41+
foo/bar/another.spec.ts
42+
"""
43+
result = self.cli('subset', '--target', '10%', 'karma', '--with', 'ng', input=subset_input)
2944
self.assert_success(result)
30-
self.assert_subset_payload('subset_result.json')
45+
self.assert_subset_payload('subset_payload.json')

tests/test_runners/test_ng.py

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)