diff --git a/pkg/gci/gci_test.go b/pkg/gci/gci_test.go
new file mode 100644
index 0000000..0d6e433
--- /dev/null
+++ b/pkg/gci/gci_test.go
@@ -0,0 +1,71 @@
+package gci
+
+import (
+	"io/ioutil"
+	"os"
+	"path"
+	"strings"
+	"testing"
+
+	"github.com/daixiang0/gci/pkg/gci/sections"
+	"github.com/daixiang0/gci/pkg/io"
+
+	"github.com/stretchr/testify/assert"
+)
+
+var testFilesPath = "internal/testdata"
+
+func isTestInputFile(file os.FileInfo) bool {
+	return !file.IsDir() && strings.HasSuffix(file.Name(), ".in.go")
+}
+
+func TestRun(t *testing.T) {
+	testFiles, err := io.FindFilesForPath(testFilesPath, isTestInputFile)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, testFile := range testFiles {
+		fileBaseName := strings.TrimSuffix(testFile, ".in.go")
+		t.Run(fileBaseName, func(t *testing.T) {
+			t.Parallel()
+
+			gciCfg, err := initializeGciConfigFromYAML(fileBaseName + ".cfg.yaml")
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			_, formattedFile, err := LoadFormatGoFile(io.File{fileBaseName + ".in.go"}, *gciCfg)
+			if err != nil {
+				t.Fatal(err)
+			}
+			expectedOutput, err := ioutil.ReadFile(fileBaseName + ".out.go")
+			if err != nil {
+				t.Fatal(err)
+			}
+			assert.Equal(t, string(expectedOutput), string(formattedFile), "output")
+			assert.NoError(t, err)
+		})
+	}
+}
+
+func TestInitGciConfigFromEmptyYAML(t *testing.T) {
+	gciCfg, err := initializeGciConfigFromYAML(path.Join(testFilesPath, "defaultValues.cfg.yaml"))
+	assert.NoError(t, err)
+	_ = gciCfg
+	assert.Equal(t, DefaultSections(), gciCfg.Sections)
+	assert.Equal(t, DefaultSectionSeparators(), gciCfg.SectionSeparators)
+	assert.False(t, gciCfg.Debug)
+	assert.False(t, gciCfg.NoInlineComments)
+	assert.False(t, gciCfg.NoPrefixComments)
+}
+
+func TestInitGciConfigFromYAML(t *testing.T) {
+	gciCfg, err := initializeGciConfigFromYAML(path.Join(testFilesPath, "configTest.cfg.yaml"))
+	assert.NoError(t, err)
+	_ = gciCfg
+	assert.Equal(t, SectionList{sections.DefaultSection{}}, gciCfg.Sections)
+	assert.Equal(t, SectionList{sections.CommentLine{"---"}}, gciCfg.SectionSeparators)
+	assert.False(t, gciCfg.Debug)
+	assert.True(t, gciCfg.NoInlineComments)
+	assert.True(t, gciCfg.NoPrefixComments)
+}
diff --git a/pkg/gci/internal/testdata/already-good.cfg.yaml b/pkg/gci/internal/testdata/already-good.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/already-good.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/already-good.in.go b/pkg/gci/internal/testdata/already-good.in.go
new file mode 100644
index 0000000..89de7a0
--- /dev/null
+++ b/pkg/gci/internal/testdata/already-good.in.go
@@ -0,0 +1,8 @@
+package main
+import (
+	"fmt"
+
+	g "github.com/golang"
+
+	"github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/already-good.out.go b/pkg/gci/internal/testdata/already-good.out.go
new file mode 100644
index 0000000..89de7a0
--- /dev/null
+++ b/pkg/gci/internal/testdata/already-good.out.go
@@ -0,0 +1,8 @@
+package main
+import (
+	"fmt"
+
+	g "github.com/golang"
+
+	"github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/comment-whithout-whitespace.cfg.yaml b/pkg/gci/internal/testdata/comment-whithout-whitespace.cfg.yaml
new file mode 100644
index 0000000..4632119
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment-whithout-whitespace.cfg.yaml
@@ -0,0 +1,2 @@
+sections:
+  - Default
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/comment-whithout-whitespace.in.go b/pkg/gci/internal/testdata/comment-whithout-whitespace.in.go
new file mode 100644
index 0000000..6ea46c9
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment-whithout-whitespace.in.go
@@ -0,0 +1,5 @@
+package proc
+
+import (
+	"context"// no separating whitespace here //nolint:confusion
+)
diff --git a/pkg/gci/internal/testdata/comment-whithout-whitespace.out.go b/pkg/gci/internal/testdata/comment-whithout-whitespace.out.go
new file mode 100644
index 0000000..0b0d6ce
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment-whithout-whitespace.out.go
@@ -0,0 +1,5 @@
+package proc
+
+import (
+	"context" // no separating whitespace here //nolint:confusion
+)
diff --git a/pkg/gci/internal/testdata/comment-with-slashslash.cfg.yaml b/pkg/gci/internal/testdata/comment-with-slashslash.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment-with-slashslash.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/comment-with-slashslash.in.go b/pkg/gci/internal/testdata/comment-with-slashslash.in.go
new file mode 100644
index 0000000..73464d9
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment-with-slashslash.in.go
@@ -0,0 +1,5 @@
+package main
+
+import (
+	"fmt" // https://pkg.go.dev/fmt
+)
diff --git a/pkg/gci/internal/testdata/comment-with-slashslash.out.go b/pkg/gci/internal/testdata/comment-with-slashslash.out.go
new file mode 100644
index 0000000..73464d9
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment-with-slashslash.out.go
@@ -0,0 +1,5 @@
+package main
+
+import (
+	"fmt" // https://pkg.go.dev/fmt
+)
diff --git a/pkg/gci/internal/testdata/comment.cfg.yaml b/pkg/gci/internal/testdata/comment.cfg.yaml
new file mode 100644
index 0000000..b99088a
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - comment( Do not forget to run Gci)
+  - default
+sectionseparators: []
+no-prefixComments: true
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/comment.in.go b/pkg/gci/internal/testdata/comment.in.go
new file mode 100644
index 0000000..38fd716
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment.in.go
@@ -0,0 +1,5 @@
+package main
+import (
+  //Do not forget to run Gci
+  "fmt"
+)
diff --git a/pkg/gci/internal/testdata/comment.out.go b/pkg/gci/internal/testdata/comment.out.go
new file mode 100644
index 0000000..e6e7839
--- /dev/null
+++ b/pkg/gci/internal/testdata/comment.out.go
@@ -0,0 +1,6 @@
+package main
+import (
+	// Do not forget to run Gci
+
+	"fmt"
+)
diff --git a/pkg/gci/internal/testdata/configTest.cfg.yaml b/pkg/gci/internal/testdata/configTest.cfg.yaml
new file mode 100644
index 0000000..766f46e
--- /dev/null
+++ b/pkg/gci/internal/testdata/configTest.cfg.yaml
@@ -0,0 +1,7 @@
+sections:
+  - default
+sectionseparators:
+  - comment(---)
+no-inlineComments: true
+no-prefixComments: true
+Debug: true
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/defaultValues.cfg.yaml b/pkg/gci/internal/testdata/defaultValues.cfg.yaml
new file mode 100644
index 0000000..e69de29
diff --git a/pkg/gci/internal/testdata/drop-prefix-comments.cfg.yaml b/pkg/gci/internal/testdata/drop-prefix-comments.cfg.yaml
new file mode 100644
index 0000000..52f15be
--- /dev/null
+++ b/pkg/gci/internal/testdata/drop-prefix-comments.cfg.yaml
@@ -0,0 +1,8 @@
+sections:
+  - comment( Std imports):std:comment( Std imports)
+  - comment( Github):prefix(github.com):comment( Github)
+sectionseparators:
+  - newline
+  - comment( --------------------------)
+  - newline
+no-prefixComments: true
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/drop-prefix-comments.in.go b/pkg/gci/internal/testdata/drop-prefix-comments.in.go
new file mode 100644
index 0000000..fbd1c05
--- /dev/null
+++ b/pkg/gci/internal/testdata/drop-prefix-comments.in.go
@@ -0,0 +1,16 @@
+package proc
+
+import (
+	// Std imports
+	"os"
+	"context" // is required
+	"fmt"
+	// Std imports
+
+	// --------------------------
+
+	// Github
+	"github.com/local/dlib/dexec"
+	"github.com/daixiang0/gci"
+	// Github
+)
diff --git a/pkg/gci/internal/testdata/drop-prefix-comments.out.go b/pkg/gci/internal/testdata/drop-prefix-comments.out.go
new file mode 100644
index 0000000..cba2a3a
--- /dev/null
+++ b/pkg/gci/internal/testdata/drop-prefix-comments.out.go
@@ -0,0 +1,16 @@
+package proc
+
+import (
+	// Std imports
+	"context" // is required
+	"fmt"
+	"os"
+	// Std imports
+
+	// --------------------------
+
+	// Github
+	"github.com/daixiang0/gci"
+	"github.com/local/dlib/dexec"
+	// Github
+)
diff --git a/pkg/gci/internal/testdata/leading-comment.cfg.yaml b/pkg/gci/internal/testdata/leading-comment.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/leading-comment.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/leading-comment.in.go b/pkg/gci/internal/testdata/leading-comment.in.go
new file mode 100644
index 0000000..b1aa143
--- /dev/null
+++ b/pkg/gci/internal/testdata/leading-comment.in.go
@@ -0,0 +1,6 @@
+package main
+
+import (
+	// foo
+	"fmt"
+)
diff --git a/pkg/gci/internal/testdata/leading-comment.out.go b/pkg/gci/internal/testdata/leading-comment.out.go
new file mode 100644
index 0000000..b1aa143
--- /dev/null
+++ b/pkg/gci/internal/testdata/leading-comment.out.go
@@ -0,0 +1,6 @@
+package main
+
+import (
+	// foo
+	"fmt"
+)
diff --git a/pkg/gci/internal/testdata/multi-line-comment.cfg.yaml b/pkg/gci/internal/testdata/multi-line-comment.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/multi-line-comment.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/multi-line-comment.in.go b/pkg/gci/internal/testdata/multi-line-comment.in.go
new file mode 100644
index 0000000..0a952e7
--- /dev/null
+++ b/pkg/gci/internal/testdata/multi-line-comment.in.go
@@ -0,0 +1,15 @@
+package proc
+
+import (
+	"context" // in-line comment
+	"fmt"
+	"os"
+
+	//nolint:depguard // A multi-line comment explaining why in
+	// this one case it's OK to use os/exec even though depguard
+	// is configured to force us to use dlib/exec instead.
+	"os/exec"
+
+	"golang.org/x/sys/unix"
+	"github.com/local/dlib/dexec"
+)
diff --git a/pkg/gci/internal/testdata/multi-line-comment.out.go b/pkg/gci/internal/testdata/multi-line-comment.out.go
new file mode 100644
index 0000000..e96ac31
--- /dev/null
+++ b/pkg/gci/internal/testdata/multi-line-comment.out.go
@@ -0,0 +1,15 @@
+package proc
+
+import (
+	"context" // in-line comment
+	"fmt"
+	"os"
+	//nolint:depguard // A multi-line comment explaining why in
+	// this one case it's OK to use os/exec even though depguard
+	// is configured to force us to use dlib/exec instead.
+	"os/exec"
+
+	"golang.org/x/sys/unix"
+
+	"github.com/local/dlib/dexec"
+)
diff --git a/pkg/gci/internal/testdata/nochar-after-import.cfg.yaml b/pkg/gci/internal/testdata/nochar-after-import.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/nochar-after-import.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/nochar-after-import.in.go b/pkg/gci/internal/testdata/nochar-after-import.in.go
new file mode 100644
index 0000000..e4ce80a
--- /dev/null
+++ b/pkg/gci/internal/testdata/nochar-after-import.in.go
@@ -0,0 +1,5 @@
+package main
+
+import (
+	"fmt"
+)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/nochar-after-import.out.go b/pkg/gci/internal/testdata/nochar-after-import.out.go
new file mode 100644
index 0000000..e4ce80a
--- /dev/null
+++ b/pkg/gci/internal/testdata/nochar-after-import.out.go
@@ -0,0 +1,5 @@
+package main
+
+import (
+	"fmt"
+)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/nolint.cfg.yaml b/pkg/gci/internal/testdata/nolint.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/nolint.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/nolint.in.go b/pkg/gci/internal/testdata/nolint.in.go
new file mode 100644
index 0000000..96c3dec
--- /dev/null
+++ b/pkg/gci/internal/testdata/nolint.in.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/forbidden/pkg" //nolint:depguard
+
+	_ "github.com/daixiang0/gci" //nolint:depguard
+)
diff --git a/pkg/gci/internal/testdata/nolint.out.go b/pkg/gci/internal/testdata/nolint.out.go
new file mode 100644
index 0000000..96c3dec
--- /dev/null
+++ b/pkg/gci/internal/testdata/nolint.out.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/forbidden/pkg" //nolint:depguard
+
+	_ "github.com/daixiang0/gci" //nolint:depguard
+)
diff --git a/pkg/gci/internal/testdata/not.a.go.file b/pkg/gci/internal/testdata/not.a.go.file
new file mode 100644
index 0000000..e69de29
diff --git a/pkg/gci/internal/testdata/simple-case.cfg.yaml b/pkg/gci/internal/testdata/simple-case.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/simple-case.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/simple-case.in.go b/pkg/gci/internal/testdata/simple-case.in.go
new file mode 100644
index 0000000..c29b5f9
--- /dev/null
+++ b/pkg/gci/internal/testdata/simple-case.in.go
@@ -0,0 +1,8 @@
+package main
+import (
+  "golang.org/x/tools"
+
+  "fmt"
+
+  "github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/simple-case.out.go b/pkg/gci/internal/testdata/simple-case.out.go
new file mode 100644
index 0000000..1c0e49f
--- /dev/null
+++ b/pkg/gci/internal/testdata/simple-case.out.go
@@ -0,0 +1,8 @@
+package main
+import (
+	"fmt"
+
+	"golang.org/x/tools"
+
+	"github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/singlechecker.go b/pkg/gci/internal/testdata/singlechecker.go
new file mode 100644
index 0000000..68e1208
--- /dev/null
+++ b/pkg/gci/internal/testdata/singlechecker.go
@@ -0,0 +1,15 @@
+package proc
+
+import (
+	"context" // in-line comment
+
+	//nolint:depguard // A multi-line comment explaining why in
+	// this one case it's OK to use os/exec even though depguard
+	// is configured to force us to use dlib/exec instead.
+	"os/exec"
+)
+
+func main() {
+	_ = context.Canceled
+	_ = exec.ErrNotFound
+}
diff --git a/pkg/gci/internal/testdata/whitespace-test.cfg.yaml b/pkg/gci/internal/testdata/whitespace-test.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/whitespace-test.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/whitespace-test.in.go b/pkg/gci/internal/testdata/whitespace-test.in.go
new file mode 100644
index 0000000..f4a4918
--- /dev/null
+++ b/pkg/gci/internal/testdata/whitespace-test.in.go
@@ -0,0 +1,7 @@
+package main
+
+import (
+  "fmt"
+  "github.com/golang" // golang
+  alias  "github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/whitespace-test.out.go b/pkg/gci/internal/testdata/whitespace-test.out.go
new file mode 100644
index 0000000..0347b51
--- /dev/null
+++ b/pkg/gci/internal/testdata/whitespace-test.out.go
@@ -0,0 +1,9 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/golang" // golang
+
+	alias "github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/with-above-comment-and-alias.cfg.yaml b/pkg/gci/internal/testdata/with-above-comment-and-alias.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-above-comment-and-alias.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/with-above-comment-and-alias.in.go b/pkg/gci/internal/testdata/with-above-comment-and-alias.in.go
new file mode 100644
index 0000000..ab81ae9
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-above-comment-and-alias.in.go
@@ -0,0 +1,7 @@
+package main
+import (
+  "fmt"
+  // golang
+  _ "github.com/golang"
+  "github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/with-above-comment-and-alias.out.go b/pkg/gci/internal/testdata/with-above-comment-and-alias.out.go
new file mode 100644
index 0000000..13c89f9
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-above-comment-and-alias.out.go
@@ -0,0 +1,9 @@
+package main
+import (
+	"fmt"
+
+	// golang
+	_ "github.com/golang"
+
+	"github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/with-alias.cfg.yaml b/pkg/gci/internal/testdata/with-alias.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-alias.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/with-alias.in.go b/pkg/gci/internal/testdata/with-alias.in.go
new file mode 100644
index 0000000..692961d
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-alias.in.go
@@ -0,0 +1,6 @@
+package main
+import (
+  "fmt"
+  g "github.com/golang"
+  "github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/with-alias.out.go b/pkg/gci/internal/testdata/with-alias.out.go
new file mode 100644
index 0000000..89de7a0
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-alias.out.go
@@ -0,0 +1,8 @@
+package main
+import (
+	"fmt"
+
+	g "github.com/golang"
+
+	"github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/with-comment-and-alias.cfg.yaml b/pkg/gci/internal/testdata/with-comment-and-alias.cfg.yaml
new file mode 100644
index 0000000..433a81e
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-comment-and-alias.cfg.yaml
@@ -0,0 +1,5 @@
+sections:
+  - Standard
+  - Default
+  - Prefix(github.com/local)
+  - Prefix(github.com/daixiang0)
\ No newline at end of file
diff --git a/pkg/gci/internal/testdata/with-comment-and-alias.in.go b/pkg/gci/internal/testdata/with-comment-and-alias.in.go
new file mode 100644
index 0000000..5457ded
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-comment-and-alias.in.go
@@ -0,0 +1,6 @@
+package main
+import (
+  "fmt"
+  _ "github.com/golang" // golang
+  "github.com/daixiang0/gci"
+)
diff --git a/pkg/gci/internal/testdata/with-comment-and-alias.out.go b/pkg/gci/internal/testdata/with-comment-and-alias.out.go
new file mode 100644
index 0000000..6b2c628
--- /dev/null
+++ b/pkg/gci/internal/testdata/with-comment-and-alias.out.go
@@ -0,0 +1,8 @@
+package main
+import (
+	"fmt"
+
+	_ "github.com/golang" // golang
+
+	"github.com/daixiang0/gci"
+)