Skip to content

Commit e18ce5c

Browse files
author
Joshua Grosso
committed
Standardize test style
Fix tests post-rebase
1 parent bdb42d8 commit e18ce5c

26 files changed

+664
-519
lines changed

README.md

+138
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,141 @@ yarn
5252

5353
**Tests are still a Work In Progress.**
5454
The tests rely on `mocha`, `chai`, `sinon`, and `sinon-chai`, and are currently a mix of system and unit tests.
55+
56+
### Naming
57+
58+
**TODO:** Split out system tests from unit tests and then revise the below guidlines.
59+
60+
These guidelines are inspired by [Better Specs { rspec guidelines with ruby }](https://www.betterspecs.org). Given that these guidelines are, by necessity, quite subjective, consider them as beneficial for the consistency rather than the "correctness" that they provide.
61+
62+
The linter should catch basic stylistic errors (e.g. prefer arrow functions unless `this` is needed).
63+
64+
---
65+
66+
When naming individual `it` blocks, the resulting test name should read like a sentence. For example: `it('returns false if the repo has no filters')`.
67+
68+
Directly describe what the test should do. Use verbs like `returns`, `errors`, `responds`, `reads`, etc. rather than prefixing tests with `should`, suffixing them with `correctly`, etc.. For example:
69+
70+
``` javascript
71+
/* Bad */
72+
it('should read globs from `.gitattributes` correctly', function () {
73+
// ...
74+
});
75+
76+
/* Good */
77+
it('reads globs from `.gitattributes`', function () {
78+
// ...
79+
});
80+
```
81+
82+
---
83+
84+
If you have the temptation to start a test with `can`, try to restructure the test to use a nested `describe` instead (whose message starts with `when`). For example:
85+
86+
``` javascript
87+
/* Bad */
88+
it('can initialize a non-LFS repo', function () {
89+
// ...
90+
});
91+
92+
/* Good */
93+
describe('when provided a non-LFS repo', () => {
94+
it('initializes the repo', function () {
95+
// ...
96+
});
97+
});
98+
```
99+
100+
---
101+
102+
For tests whose behavior varies cross-platform, surround the tests with a `process.platform` test. Be sure to add tests for all platforms where behavior could vary, even if you cannot run them locally. Because CI will run on Windows, macOS, and Linux, this should not be an obstacle to thorough test coverage. For example:
103+
104+
``` javascript
105+
/* Bad */
106+
describe('when on Windows', () => {
107+
beforeEach(() => {
108+
sinon.stub(process, 'platform').returns('win32');
109+
});
110+
111+
it('runs the provided command', function () {
112+
// ...
113+
});
114+
});
115+
116+
describe('when on macOS', () => {
117+
beforeEach(() => {
118+
sinon.stub(process, 'platform').returns('darwin');
119+
});
120+
121+
it('runs the provided command', function () {
122+
// ...
123+
});
124+
});
125+
126+
describe('when on Linux', () => {
127+
beforeEach(() => {
128+
sinon.stub(process, 'platform').returns('linux');
129+
});
130+
131+
it('runs the provided command', function () {
132+
// ...
133+
});
134+
});
135+
136+
/* Good */
137+
switch (process.platform) {
138+
case 'win32':
139+
it('runs the provided command', function () {
140+
// ...
141+
});
142+
break;
143+
case 'macOS':
144+
it('runs the provided command', function () {
145+
// ...
146+
});
147+
break;
148+
case 'linux':
149+
it('runs the provided command', function () {
150+
// ...
151+
});
152+
break;
153+
}
154+
```
155+
156+
---
157+
158+
When referring to parameters, use `provided` rather than `passed-in`, `given`, etc. For example:
159+
160+
``` javascript
161+
/* Bad */
162+
it('runs the passed-in command', function () {
163+
// ...
164+
});
165+
166+
/* Good */
167+
it('runs the provided command', function () {
168+
// ...
169+
});
170+
```
171+
172+
---
173+
174+
Each implementation file should correspond to a similarly-named `<file name>.spec.js` test file in the same relative location. For example, `src/callbacks/check.js` should have a test file located in `test/tests/callbacks/check.spec.js`.
175+
176+
The top-level `describe` should be named after the file. `describe`s for each function should be named after the function itself. On a related note, each function should have its own `describe` block, even if there is only `it` block inside it. In the case that a function does not have a pre-defined name (e.g. it's an anonymous function exported as the default), refer to it as `the default export`. For example:
177+
178+
``` javascript
179+
/* For named exports: */
180+
describe('helpers', () => { // Named after the file name, `helpers.spec.js`
181+
describe('hasLfsFilters', () => { // Named after the exported function name, `hasLfsFilters`
182+
// ...
183+
});
184+
});
185+
186+
/* For default exports: */
187+
describe('check', () => {
188+
describe('the default export', () => {
189+
// ...
190+
});
191+
});
192+
```

src/constants.js

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export const LFS_FILTER_NAME = 'nodegit_lfs';
55
export const regex = {
66
LFS: /(?:git-lfs\/\s+)?(\d+)(?:.(\d+))?(?:.(\d+))?.*/,
77
GIT: /(?:git\s+version\s+)(\d+\.){2}\d+/,
8-
VERSION: /(\d+\.){2}\d+/,
98
TRACK: /([a-zA-Z*.]+(?="))/g,
109
SKIPPED_BYTES: /[\d]+\s+B\s+(?=skipped)/g,
1110
SKIPPED_FILES: /[\d]\s+(?=skipped)/g,

test/runner.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,16 @@ beforeEach(function () {
7777

7878
return NodeGitLFS.LFS.register()
7979
.then(() => setupEmptyTestRepo())
80+
.then(() => NodeGitLFS.Repository.open(emptyRepoPath))
81+
.then((emptyRepo) => {
82+
this.emptyRepo = emptyRepo;
83+
})
8084
.then(() => setupLfsTestRemote())
81-
.then(() => setupLfsTestRepo());
85+
.then(() => setupLfsTestRepo())
86+
.then(() => NodeGitLFS.Repository.open(lfsTestRepoPath))
87+
.then((lfsTestRepo) => {
88+
this.lfsTestRepo = lfsTestRepo;
89+
});
8290
});
8391

8492
after(function () {

test/tests/callbacks/apply.spec.js

+27-27
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const track = (repo, globs) => {
2929
describe('apply', () => {
3030
beforeEach(function () {
3131
const {
32+
lfsTestRepo,
3233
NodeGitLFS
3334
} = this;
3435

@@ -68,15 +69,15 @@ describe('apply', () => {
6869
};
6970

7071
this.trackTestFile = () =>
71-
track(this.repo, [this.testFileName])
72+
track(lfsTestRepo, [this.testFileName])
7273
.then(() => createDummyFile(
7374
path.join(lfsTestRepoPath, this.testFileName),
7475
testFileSize
7576
))
7677
.then((contents) => {
7778
this.contents = contents;
7879
})
79-
.then(() => this.commitFile(this.repo, this.testFileName, 'LFS filter tests'));
80+
.then(() => this.commitFile(lfsTestRepo, this.testFileName, 'LFS filter tests'));
8081

8182
this.verifyTestFileTracked = () =>
8283
fse.readFile(path.join(lfsTestRepoPath, this.testFileName), 'utf8')
@@ -87,37 +88,36 @@ describe('apply', () => {
8788
.then((pointer) => {
8889
expect(pointer).to.have.string(`size ${testFileSize}`);
8990
});
90-
91-
return NodeGitLFS.Repository.open(lfsTestRepoPath)
92-
.then((repo) => {
93-
this.repo = repo;
94-
});
9591
});
9692

97-
it('Clean', function () {
98-
const {
93+
describe('clean', () => {
94+
it('cleans LFS-tracked files', function () {
95+
const {
9996
trackTestFile,
100-
verifyTestFileTracked
97+
verifyTestFileTracked
10198
} = this;
10299

103-
return trackTestFile()
104-
.then(() => verifyTestFileTracked());
100+
return trackTestFile()
101+
.then(() => verifyTestFileTracked());
102+
});
105103
});
106104

107-
it('Smudge', function () {
108-
const {
109-
NodeGitLFS,
110-
repo,
111-
testFileName,
112-
trackTestFile,
113-
verifyTestFileTracked
114-
} = this;
105+
describe('smudge', () => {
106+
it('smudges LFS blobs', function () {
107+
const {
108+
NodeGitLFS,
109+
lfsTestRepo,
110+
testFileName,
111+
trackTestFile,
112+
verifyTestFileTracked
113+
} = this;
115114

116-
return trackTestFile()
117-
.then(() => createDummyFile(path.join(lfsTestRepoPath, testFileName), 5))
118-
.then(() => NodeGitLFS.Checkout.head(repo, {
119-
checkoutStrategy: NodeGitLFS.Checkout.STRATEGY.FORCE
120-
}))
121-
.then(() => verifyTestFileTracked());
122-
}).timeout(10000);
115+
return trackTestFile()
116+
.then(() => createDummyFile(path.join(lfsTestRepoPath, testFileName), 5))
117+
.then(() => NodeGitLFS.Checkout.head(lfsTestRepo, {
118+
checkoutStrategy: NodeGitLFS.Checkout.STRATEGY.FORCE
119+
}))
120+
.then(() => verifyTestFileTracked());
121+
}).timeout(10000);
122+
});
123123
});

test/tests/callbacks/check.spec.js

+48-49
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,76 @@ import {
55
Error
66
} from 'nodegit';
77

8-
import {
9-
lfsTestRepoPath
10-
} from '../../constants';
11-
128
import track from '../../../build/src/commands/track';
139
import checkCallback from '../../../build/src/callbacks/check';
1410

1511
describe('check', () => {
1612
beforeEach(function () {
1713
const {
18-
NodeGitLFS
14+
lfsTestRepo
1915
} = this;
2016

2117
this.check = fileName => checkCallback({
2218
path: () => fileName,
23-
repo: () => this.repo
19+
repo: () => lfsTestRepo
2420
});
25-
26-
return NodeGitLFS.Repository.open(lfsTestRepoPath)
27-
.then((repo) => {
28-
this.repo = repo;
29-
});
3021
});
3122

32-
it('returns `OK` for a file directly specified in .gitattributes', function () {
33-
const {
34-
check,
35-
repo
36-
} = this;
23+
describe('the default export', () => {
24+
describe('when the provided file is directly specified in `.gitattributes`', () => {
25+
it('returns `OK` for the provided file', function () {
26+
const {
27+
check,
28+
lfsTestRepo
29+
} = this;
3730

38-
return track(repo, ['test.txt'])
39-
.then(() => check('test.txt'))
40-
.then((result) => {
41-
expect(result).to.equal(Error.CODE.OK);
31+
return track(lfsTestRepo, ['test.txt'])
32+
.then(() => check('test.txt'))
33+
.then((result) => {
34+
expect(result).to.equal(Error.CODE.OK);
35+
});
4236
});
43-
});
37+
});
4438

45-
it('returns `OK` for a file included in a glob in .gitattributes', function () {
46-
const {
47-
check,
48-
repo
49-
} = this;
39+
describe('when the provided file is included in a glob in `.gitattributes`', () => {
40+
it('returns `OK` for the provided file', function () {
41+
const {
42+
check,
43+
lfsTestRepo
44+
} = this;
5045

51-
return track(repo, ['*.txt'])
52-
.then(() => check('test.txt'))
53-
.then((result) => {
54-
expect(result).to.equal(Error.CODE.OK);
46+
return track(lfsTestRepo, ['*.txt'])
47+
.then(() => check('test.txt'))
48+
.then((result) => {
49+
expect(result).to.equal(Error.CODE.OK);
50+
});
5551
});
56-
});
52+
});
5753

58-
it('returns `PASSTHROUGH` for a file not included in .gitattributes', function () {
59-
const {
60-
check,
61-
repo
62-
} = this;
54+
describe('when the provided file is not included in `.gitattributes`', () => {
55+
it('returns `PASSTHROUGH`', function () {
56+
const {
57+
check,
58+
lfsTestRepo
59+
} = this;
6360

64-
return track(repo, ['other.txt'])
65-
.then(() => check('test.txt'))
66-
.then((result) => {
67-
expect(result).to.equal(Error.CODE.PASSTHROUGH);
61+
return track(lfsTestRepo, ['other.txt'])
62+
.then(() => check('test.txt'))
63+
.then((result) => {
64+
expect(result).to.equal(Error.CODE.PASSTHROUGH);
65+
});
6866
});
69-
});
67+
});
7068

71-
it('returns `PASSTHROUGH` on error', function () {
72-
const {
73-
check
74-
} = this;
69+
it('returns `PASSTHROUGH` on error', function () {
70+
const {
71+
check
72+
} = this;
7573

76-
return check('test.txt')
77-
.then((result) => {
78-
expect(result).to.equal(Error.CODE.PASSTHROUGH);
79-
});
74+
return check('test.txt')
75+
.then((result) => {
76+
expect(result).to.equal(Error.CODE.PASSTHROUGH);
77+
});
78+
});
8079
});
8180
});

test/tests/callbacks/initialize.spec.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ import {
77

88
import initialize from '../../../build/src/callbacks/initialize';
99

10-
describe('Initialize', () => {
11-
it('returns `OK`', () => {
12-
expect(initialize()).to.equal(Error.CODE.OK);
10+
describe('initialize', () => {
11+
describe('the default export', () => {
12+
it('returns `OK`', () => {
13+
expect(initialize()).to.equal(Error.CODE.OK);
14+
});
1315
});
1416
});

0 commit comments

Comments
 (0)