1 TDD learning

1.1 about TDD

concept

Test-driven Development, English full name test-driven Development, referred to as TDD, is a new Development method different from the traditional software Development process. It requires that you write test code before you write the code for a feature, and then only write the code for the feature that makes the test pass, and the test drives the development.

TDD three principles

  1. You are not allowed to write any production code except to pass a unit test.
  2. You are only allowed to write just enough to fail in a unit test.
  3. You can only write production code that passes one unit test at a time, no more.

refactoring

Code refactoring refers to making any change to software code to increase readability or simplify structure without affecting the output.

1.2 About benchmarking

What is a benchmark

Benchmarking measures the performance of an application under a fixed workload. In Go, a Benchmark function is written like a normal test function, but prefixes it with a parameter of type * testing.b. The * testing.b parameter provides a method similar to * testing.t, with additional methods related to performance measurement. It also provides an integer N that specifies the number of cycles the operation is executed.

Benchmarking versus stress testing

Benchmarking can be thought of as a stress test for a system. Benchmarking is simple, straightforward, and easy to test without concern for business logic. The data can be generated by tools and does not require authenticity. Stress testing generally considers business logic and requires real data.

The role of benchmarking

For most Web applications, the bottleneck of the whole system lies in the database; The reason is simple: other factors in Web applications, such as network bandwidth, load balancing nodes, application servers (including CPU, memory, disk lights, connection count, etc.), and caching, can easily be improved by horizontal scaling (commonly known as adding machines). As for MySQL, due to the requirement of data consistency, it cannot disperse the pressure of writing data to the database by adding machines. Although it can be alleviated by pre-caching (Redis, etc.), read-write separation, and separate libraries and tables, it is too limited compared to the horizontal scaling of other components of the system.

The function of a database benchmark is to analyze the performance of the database under the current configuration (including hardware configuration, OS configuration, and database configuration), find out the performance threshold of MySQL, and adjust the configuration according to the actual system requirements.

1.3 Complete the “Iteration” tutorial

Writing tests first

package iteration import "testing" func TestRepeat(t *testing.T) { repeated := Repeat("a") expected := "aaaaa" if repeated ! = expected { t.Errorf("expected '%q' but got '%q'", expected, repeated) } }Copy the code

Try to run the tests

Let failed tests run with minimal code

package iteration

func Repeat(character string) string {
	return ""
}
Copy the code

Results:

Write implementations that pass tests

package iteration

func Repeat(character string) string {
	var repeated string
	for i := 0; i < 5; i++ {
		repeated = repeated + character
	}
	return repeated
}
Copy the code

Results:

refactoring

Modify code for standardization, simplicity, readability, etc. :

const repeatCount = 5

func Repeat(character string) string {
    var repeated string
    for i := 0; i < repeatCount; i++ {
        repeated += character
    }
    return repeated
}
Copy the code
The benchmark
func BenchmarkRepeat(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Repeat("a")
	}
}
Copy the code

It is worth noting that Goland can quickly generate test code:Results:

Complete the exercises in the “Iteration” chapter

Modify the test code so that the caller can specify how many times the character is repeated, and then fix the code

Modify the test code:Then run the test:You can see that you need to modify the production code to pass the unit tests:Pass the test:

Write an ExampleRepeat to complete your function documentation

The requirements are met.

Look at the strings package. Find functions that you think might be useful, and write some tests on them.

Test the Count function

Test code:

	s := "go mod init github.com/Winszheng"
	fmt.Printf("test1: %d\n", strings.Count(s, "s"))
	fmt.Printf("test2: %d\n", strings.Count(s, "g"))
Copy the code

Results:

3 Select sort TDD practice report

Writing tests first

func TestSelectSort(t *testing.T) { initial := []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1} SelectSort(initial) expected := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} for i:=0; i<10; i++ { if initial[i]! =expected[i] { t.Errorf("expected %v but get %v\n", expected, initial) } } }Copy the code

Try to run the tests

Let failed tests run with minimal code

func SelectSort(arr []int) ([]int) {
	return arr
}
Copy the code

Results:

Write code that passes tests

Code:

func SelectSort(arr []int) ([]int) {
	for i := 0; i < len(arr)-1; i++ {
		min := i
		for j := i+1; j < len(arr); j++ {
			if arr[j] < arr[min] {
				min = j
			}
		}
		arr[min], arr[i] = arr[i], arr[min]
	}
	return arr
}
Copy the code

Results:

refactoring

Refactoring like the tutorial:

func SelectSort(arr []int) ([]int) {
	len := len(arr)
	for i := 0; i < len - 1; i++ {
		min := i
		for j := i+1; j < len; j++ {
			if arr[j] < arr[min] {
				min = j
			}
		}
		arr[min], arr[i] = arr[i], arr[min]
	}
	return arr
}
Copy the code

The benchmark

func Benchmark(b *testing.B) {
	for i := 0; i < b.N; i++ {
		initial := []int{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}
		SelectSort(initial)
	}
}
Copy the code

Run the benchmark:

4 reference

Test-Driven Development(TDD) in Go

The benchmark

How do I write goDoc