-
-
Notifications
You must be signed in to change notification settings - Fork 685
Add "counter", a write-the-test-suite exercise #168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ | |
| "circular-buffer", | ||
| "robot-name", | ||
| "react", | ||
| "counter", | ||
| "custom-set", | ||
| "atbash-cipher", | ||
| "phone-number", | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| package counter | ||
|
|
||
| // Define your tests here |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package counter | ||
|
|
||
| // NOTE: This file is called example.go and not example_test.go because if it's | ||
| // called example_test.go it will get picked up by the test suite and fail | ||
| // because COUNTER_IMPL isn't set (see maker.go). | ||
|
|
||
| import "testing" | ||
|
|
||
| func TestNoAdd(t *testing.T) { | ||
| counter := makeCounter() | ||
| if counter.Lines() != 0 { | ||
| t.Errorf("Lines mismatch: got %d, expected %d", counter.Lines(), 0) | ||
| } | ||
| if counter.Letters() != 0 { | ||
| t.Errorf("Letters mismatch: got %d, expected %d", counter.Letters(), 0) | ||
| } | ||
| if counter.Characters() != 0 { | ||
| t.Errorf("Characters mismatch: got %d, expected %d", counter.Characters(), 0) | ||
| } | ||
| } | ||
|
|
||
| func TestEmptyString(t *testing.T) { | ||
| counter := makeCounter() | ||
| counter.AddString("") | ||
| if counter.Lines() != 0 { | ||
| t.Errorf("Lines mismatch: got %d, expected %d", counter.Lines(), 0) | ||
| } | ||
| if counter.Letters() != 0 { | ||
| t.Errorf("Letters mismatch: got %d, expected %d", counter.Letters(), 0) | ||
| } | ||
| if counter.Characters() != 0 { | ||
| t.Errorf("Characters mismatch: got %d, expected %d", counter.Characters(), 0) | ||
| } | ||
| } | ||
|
|
||
| func TestASCIIString(t *testing.T) { | ||
| counter := makeCounter() | ||
| counter.AddString("Hello\nworld!") | ||
| if counter.Lines() != 2 { | ||
| t.Errorf("Lines mismatch: got %d, expected %d", counter.Lines(), 2) | ||
| } | ||
| if counter.Letters() != 10 { | ||
| t.Errorf("Letters mismatch: got %d, expected %d", counter.Letters(), 10) | ||
| } | ||
| if counter.Characters() != 12 { | ||
| t.Errorf("Characters mismatch: got %d, expected %d", counter.Characters(), 12) | ||
| } | ||
| } | ||
|
|
||
| func TestRussianString(t *testing.T) { | ||
| counter := makeCounter() | ||
| // Lifted this translation from the ru.po file of GNU hello | ||
| counter.AddString("здравствуй, мир\n") | ||
| if counter.Lines() != 1 { | ||
| t.Errorf("Lines mismatch: got %d, expected %d", counter.Lines(), 2) | ||
| } | ||
| if counter.Letters() != 13 { | ||
| t.Errorf("Letters mismatch: got %d, expected %d", counter.Letters(), 10) | ||
| } | ||
| if counter.Characters() != 16 { | ||
| t.Errorf("Characters mismatch: got %d, expected %d", counter.Characters(), 12) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package counter | ||
|
|
||
| import "unicode" | ||
|
|
||
| // Incorrect implementation: wrongly counts lines. | ||
| type Impl1 struct { | ||
| lines, characters, letters int | ||
| } | ||
|
|
||
| func (c *Impl1) AddString(s string) { | ||
| for _, char := range s { | ||
| if char == '\n' { | ||
| c.lines++ | ||
| } else if unicode.IsLetter(char) { | ||
| c.letters++ | ||
| } | ||
| c.characters++ | ||
| } | ||
| } | ||
|
|
||
| func (c Impl1) Lines() int { return c.lines } | ||
| func (c Impl1) Letters() int { return c.letters } | ||
| func (c Impl1) Characters() int { return c.characters } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package counter | ||
|
|
||
| // Incorrect implementation: wrongly determines characters. | ||
| type Impl2 struct { | ||
| newlines, characters, letters int | ||
| lastChar rune | ||
| } | ||
|
|
||
| func (c *Impl2) AddString(s string) { | ||
| for _, char := range s { | ||
| c.lastChar = char | ||
| if char == '\n' { | ||
| c.newlines++ | ||
| } else if (char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z') { | ||
| c.letters++ | ||
| } | ||
| c.characters++ | ||
| } | ||
| } | ||
|
|
||
| func (c Impl2) Lines() int { | ||
| switch { | ||
| case c.characters == 0: | ||
| return 0 | ||
| case c.lastChar == '\n': | ||
| return c.newlines | ||
| default: | ||
| return c.newlines + 1 | ||
| } | ||
| } | ||
|
|
||
| func (c Impl2) Letters() int { return c.letters } | ||
| func (c Impl2) Characters() int { return c.characters } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package counter | ||
|
|
||
| import "unicode" | ||
|
|
||
| // Incorrect implementation: assumes ASCII. | ||
| type Impl3 struct { | ||
| newlines, characters, letters int | ||
| lastChar rune | ||
| } | ||
|
|
||
| func (c *Impl3) AddString(s string) { | ||
| for i := 0; i < len(s); i++ { | ||
| char := rune(s[i]) | ||
| c.lastChar = char | ||
| if char == '\n' { | ||
| c.newlines++ | ||
| } else if unicode.IsLetter(char) { | ||
| c.letters++ | ||
| } | ||
| c.characters++ | ||
| } | ||
| } | ||
|
|
||
| func (c Impl3) Lines() int { | ||
| switch { | ||
| case c.characters == 0: | ||
| return 0 | ||
| case c.lastChar == '\n': | ||
| return c.newlines | ||
| default: | ||
| return c.newlines + 1 | ||
| } | ||
| } | ||
|
|
||
| func (c Impl3) Letters() int { return c.letters } | ||
| func (c Impl3) Characters() int { return c.characters } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package counter | ||
|
|
||
| import "unicode" | ||
|
|
||
| // Correct implementation | ||
| type Impl4 struct { | ||
| newlines, characters, letters int | ||
| lastChar rune | ||
| } | ||
|
|
||
| func (c *Impl4) AddString(s string) { | ||
| for _, char := range s { | ||
| c.lastChar = char | ||
| if char == '\n' { | ||
| c.newlines++ | ||
| } else if unicode.IsLetter(char) { | ||
| c.letters++ | ||
| } | ||
| c.characters++ | ||
| } | ||
| } | ||
|
|
||
| func (c Impl4) Lines() int { | ||
| switch { | ||
| case c.characters == 0: | ||
| return 0 | ||
| case c.lastChar == '\n': | ||
| return c.newlines | ||
| default: | ||
| return c.newlines + 1 | ||
| } | ||
| } | ||
|
|
||
| func (c Impl4) Letters() int { return c.letters } | ||
| func (c Impl4) Characters() int { return c.characters } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package counter | ||
|
|
||
| type Counter interface { | ||
| AddString(string) | ||
|
|
||
| Lines() int | ||
| Letters() int | ||
| Characters() int | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package counter | ||
|
|
||
| import ( | ||
| "log" | ||
| "os" | ||
| ) | ||
|
|
||
| // A little trick to help test the various versions, | ||
| // set the COUNTER_IMPL environment variable to the | ||
| // number of the implementation you want to test. | ||
| // E.g. run `COUNTER_IMPL=4 go test` to get Impl4. | ||
|
|
||
| func makeCounter() Counter { | ||
| switch os.Getenv("COUNTER_IMPL") { | ||
| case "1": | ||
| return &Impl1{} | ||
| case "2": | ||
| return &Impl2{} | ||
| case "3": | ||
| return &Impl3{} | ||
| case "4": | ||
| return &Impl4{} | ||
| case "": | ||
| log.Fatalf("Don't forget to set COUNTER_IMPL") | ||
| default: | ||
| log.Fatalf("Unknown COUNTER_IMPL value: %s", os.Getenv("COUNTER_IMPL")) | ||
| } | ||
| panic("not reachable, but go's return analysis needs it") | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename the file to
example_test.go?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't that automatically include it in the files sent to the user?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, anything with
examplein the path (not just the name of the file) will be excluded from the payload to the user.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After trying this I remembered why it doesn't work. The example_test.go gets picked up by go test in the travis and fails since you have to explicitly set an environment variable to choose an implementation to test with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right. Yepp, that makes sense! Would you add a comment to that effect in the file itself? I can see myself forgetting this and going through the exact same set of questions six months from now.