Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions 25-testing/01-testify/.README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Testing

In this task, you need to test the function `{{ index . "name" }}` in Go using **`testify/assert`**.

## Function Description

The implementation is available in [exercise_test.go](exercise_test.go), if needed.
Below we show some examples of the expected behaviors.

{{- if eq (index . "name") "strstr" }}

### `strstr(str string, substr string) int`

- Returns the **index of the first occurrence** of `substr` in `str`.
- Returns `0` if `substr` is empty.
- Returns `-1` if `substr` is not found.

**Example:**

```go
strstr("hello world", "lo") // 3

strstr("hello", "Go") // -1

strstr("abc", "") // 0
```
{{- end }}
{{- if eq (index . "name") "strncat" }}

### `strncat(dest *string, src string, n int)`

- Appends at most `n` characters from `src` to `dest`.
- Modifies `dest` in place

**Example:**

```go
dest := "Hello"
strncat(&dest, "World", 3) // dest == "HelloWor"

dest := "Hi"
strncat(&dest, "All", 10) // dest == "HiAll"

dest := ""
strncat(&dest, "Go", 1) // dest == "G"
```
{{- end }}
{{- if eq (index . "name") "strncpy" }}

### `strncpy(dest *string, src string, n int)`

- Copies at most `n` characters from `src` to `dest`.
- Modifies `dest` in place

**Example:**

```go
dest := "Hello"
strncpy(&dest, "Go", 2) // dest == "Go"

dest := ""
strncpy(&dest, "World", 3) // dest == "Wor"

dest := "Hi"
strncpy(&dest, "", 1) // dest == ""
```
{{- end }}

## Requirements
1. Use only assert statements from the [testify/assert](https://pkg.go.dev/github.com/stretchr/testify/assert) package.
2. Do not modify the provided function signature.
3. Write exactly three test functions for the function `{{ index . "name" }}`.

## Needed test functions:

{{- if eq (index . "name") "strstr" }}

- `StrStrMatch(t *testing.T)` — test when the substring exists
- `StrStrNoMatch(t *testing.T)` — test when the substring does not exist
- `StrStrEmptySubString(t *testing.T)` — test when the substring is empty
{{- end }}
{{- if eq (index . "name") "strncat" }}

- `StrNCatInbounds(t *testing.T)` — append a part of the source within index bounds
- `StrNCatOutOfBounds(t *testing.T)` — append more than the source length
- `StrNCatEmptySource(t *testing.T)` — append from an empty source
{{- end }}
{{- if eq (index . "name") "strncpy" }}

- `StrNCpyINbounds(t *testing.T)` — copy part of the source within index bounds
- `StrNCpyEmptyDestination(t *testing.T)` — copy into an empty destination
- `StrNCpyEmptySource(t *testing.T)` — copy from an empty source
{{- end }}

Insert the code into the file `exercise.go` at the placeholder `// INSERT YOUR CODE HERE`.
115 changes: 115 additions & 0 deletions 25-testing/01-testify/.exercise_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package testimony

import (
"os"
"regexp"
"testing"
)

const requiredAsserts = 3

func TestStudentUsesAssertions(t *testing.T) {
src, err := os.ReadFile("exercise.go")
if err != nil {
t.Fatalf("cannot read exercise.go: %v", err)
}

source := string(src)

re := regexp.MustCompile(`assert\.\w+\s*\(`)
if !re.MatchString(source) {
t.Fatalf("no assert.* call found in exercise.go")
}
}

func TestStudentHasEnoughAsserts(t *testing.T) {
src, err := os.ReadFile("exercise.go")
if err != nil {
t.Fatalf("cannot read exercise.go: %v", err)
}

source := string(src)

re := regexp.MustCompile(`assert\.\w+\s*\(`)
matches := re.FindAllString(source, -1)

if len(matches) < requiredAsserts {
t.Fatalf("not enough assert calls: found %d, required %d", len(matches), requiredAsserts)
}
}

func TestNoTrivialAssertions(t *testing.T) {
src, err := os.ReadFile("exercise.go")
if err != nil {
t.Fatalf("cannot read exercise.go: %v", err)
}

source := string(src)

patterns := []string{
`assert\.False\s*\(\s*t\s*,\s*false\s*[,)]`,
`assert\.True\s*\(\s*t\s*,\s*true\s*[,)]`,
`assert\.Equal\s*\(\s*t\s*,\s*true\s*,\s*true\s*[,)]`,
`assert\.Equal\s*\(\s*t\s*,\s*false\s*,\s*false\s*[,)]`,
}

for _, p := range patterns {
re := regexp.MustCompile(p)
if re.MatchString(source) {
t.Fatalf("trivial assertion detected")
}
}
}

{{- if eq (index . "name") "strstr"}}

func strstr(str string, substr string) int {
if substr == "" {
return 0
}

for i := 0; i <= len(str)-len(substr); i++ {
if str[i:i+len(substr)] == substr {
return i
}
}

return -1
}
{{- end}}
{{- if eq (index . "name") "strncat"}}

func strncat(dest *string, src string, n int) {
if n > len(src) {
n = len(src)
}
*dest += src[:n]
}
{{- end}}
{{- if eq (index . "name") "strncpy"}}

func strncpy(dest *string, src string, n int) {
if n > len(src) {
n = len(src)
}
*dest = src[:n]
}
{{- end}}

func TestRunStudentTests(t *testing.T) {
{{- if eq (index . "name") "strstr"}}
t.Run("StrStrMatch", StrStrMatch)
t.Run("StrStrNoMatch", StrStrNoMatch)
t.Run("StrStrEmptySubString", StrStrEmptySubString)
{{- end}}
{{- if eq (index . "name") "strncat"}}
t.Run("StrNCatInbounds", StrNCatInbounds)
t.Run("StrNCatOutOfBounds", StrNCatOutOfBounds)
t.Run("StrNCatEmptySource", StrNCatEmptySource)
{{- end}}
{{- if eq (index . "name") "strncpy"}}
t.Run("StrNCpyINbounds", StrNCpyINbounds)
t.Run("StrNCpyEmptyDestination", StrNCpyEmptyDestination)
t.Run("StrNCpyEmptySource", StrNCpyEmptySource)
{{- end}}
}
13 changes: 13 additions & 0 deletions 25-testing/01-testify/exercise.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package testimony

import (
"testing"

"github.com/stretchr/testify/assert"
)

// DO NOT REMOVE THIS COMMENT
//go:generate go run ../../exercises-cli.go -student-id=$STUDENT_ID generate


// INSERT YOUR CODE HERE
5 changes: 5 additions & 0 deletions 25-testing/01-testify/exercise.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: testimony
input:
- name: strstr
- name: strncat
- name: strncpy
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ EXERCISE_DIRS=\
21-channels \
22-context \
23-misc \
24-generics
24-generics \
25-testing

# LAB subdirs
LAB_DIRS=\
Expand Down
Loading