diff --git a/ListNode.java b/ListNode.java
new file mode 100644
index 00000000..13acea9b
--- /dev/null
+++ b/ListNode.java
@@ -0,0 +1,68 @@
+package com.blankj.structure;
+
+/**
+ * <pre>
+ *     author: Blankj
+ *     blog  : http://blankj.com
+ *     time  : 2017/05/18
+ *     desc  :
+ * </pre>
+ */
+public class ListNode {
+
+    public int      val;
+    public ListNode next;
+
+    public ListNode(int x) {
+        val = x;
+    }
+
+    /**
+     * 创建测试数据
+     *
+     * @param data [XX,XX,XX]
+     * @return {@link ListNode}
+     */
+    public static ListNode createTestData(String data) {
+        if (data.equals("[]")) return null;
+        data = data.substring(1, data.length() - 1);
+        String[] split = data.split(",");
+        int len = split.length;
+        ListNode[] listNode = new ListNode[len + 1];
+        listNode[0] = new ListNode(Integer.valueOf(split[0]));
+        for (int i = 1; i < len; i++) {
+            listNode[i] = new ListNode(Integer.valueOf(split[i]));
+            listNode[i - 1].next = listNode[i];
+        }
+        return listNode[0];
+    }
+
+    public static void print(ListNode listNode) {
+        if (listNode == null) {
+            System.out.println("null");
+            return;
+        }
+        StringBuilder str = new StringBuilder("[" + String.valueOf(listNode.val));
+        ListNode p = listNode.next;
+        while (p != null) {
+            str.append(",").append(String.valueOf(p.val));
+            p = p.next;
+        }
+        System.out.println(str.append("]"));
+    }
+
+    public String toString(ListNode listNode) {
+        if (listNode == null) {
+            System.out.println("null");
+            return "";
+        }
+        StringBuilder str = new StringBuilder("[" + String.valueOf(listNode.val));
+        ListNode p = listNode.next;
+        while (p != null) {
+            str.append(",").append(String.valueOf(p.val));
+            p = p.next;
+        }
+        str.append("]");
+        return str.toString();
+    }
+}
diff --git a/SolutionTest.java b/SolutionTest.java
new file mode 100644
index 00000000..124bbede
--- /dev/null
+++ b/SolutionTest.java
@@ -0,0 +1,103 @@
+package com.blankj.hard._025;
+import com.blankj.structure.ListNode;
+import org.hamcrest.CoreMatchers;
+import org.junit.jupiter.api.Test;
+import java.lang.ArithmeticException;
+import java.util.List;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SolutionTest {
+    Solution solution = new Solution();
+
+    @Test
+    public void TestReverseKGroupsWithHeadNull_1(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[]"), -1);
+        assertNull(actual);
+    }
+
+
+    @Test
+    public void TestReverseKGroupsWithHeadNull_2(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[]"), 0);
+        assertNull(actual);
+    }
+
+
+
+
+    @Test
+    public void TestReverseKGroupsWithHeadNull_3(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[]"), 1);
+        assertNull(actual);
+    }
+
+    @Test
+    public void TestReverseKGroupWith_k_isZero() throws Exception {
+        try {
+            ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), 0);
+            fail("Not throw exception");
+        } catch (Exception e) {
+            assertThat(e, CoreMatchers.instanceOf(ArithmeticException.class));
+            assertEquals(e.getMessage(), "/ by zero");
+        }
+    }
+
+    @Test
+    public void TestReverseKGroupWith_k_isN() throws Exception {
+        try {
+            ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), -1);
+            fail("Not throw exception");
+        } catch (Exception e) {
+            assertThat(e, CoreMatchers.instanceOf(ArithmeticException.class));
+            assertEquals(e.getMessage(), "/ k must greater than 0");
+        }
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), 1);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[1]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_greaterTh(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), 2);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[1]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_isSmThanLengthOfListNode(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1,2,3]"), 2);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[2,1,3]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_isEqualToLength(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1,2,3]"), 3);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[3,2,1]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+//    public static void main(String[] args) {
+//        Solution solution = new Solution();
+//        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1,2,3,4,5,6,7,8]"), 3);
+//        String actualString = actual.toString(actual);
+//        ListNode expect = ListNode.createTestData("[3,2,1,6,5,4,7,8]");
+//        String expectString = expect.toString(expect);
+//        assertEquals(expectString, actualString);
+//        assert
+//    }
+}
\ No newline at end of file
diff --git a/SolutionTest028.java b/SolutionTest028.java
new file mode 100644
index 00000000..73862ed7
--- /dev/null
+++ b/SolutionTest028.java
@@ -0,0 +1,52 @@
+//test use MCC cover
+
+package com.blankj.easy._028;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SolutionTest {
+    Solution solution = new Solution();
+    @Test
+    public void TestImplementStrWithNeedleIsPartOfHayStack(){
+        Integer actual = solution.strStr("1,2,3,4", "1,2");
+        Integer expected = 0;
+        assertEquals(actual, expected);
+    }
+
+    @Test
+    public void TestImplementStrWithNeedleIsNotPartOfHayStack1(){
+        Integer actual = solution.strStr("1,2,3,4", "2,1");
+        Integer expected = -1;
+        assertEquals(actual, expected);
+    }
+
+    @Test
+    public void TestImplementStrWithNeedleIsNone(){
+        Integer actual = solution.strStr("1,2,3,4", "");
+        Integer expected = 0;
+        assertEquals(actual, expected);
+    }
+
+    @Test
+    public void TestImplementStrWithLenNeedleGreaterThanLenHayStack(){
+        Integer actual = solution.strStr("1,2,3,4", "1,2,3,4,5");
+        Integer expected = -1;
+        assertEquals(actual, expected);
+    }
+
+    @Test
+    public void TestImplementStrWithLenNeedleEqualToLenHayStack(){
+        Integer actual = solution.strStr("1,2,3,4", "1,2,3,4");
+        Integer expected = 0;
+        assertEquals(actual, expected);
+    }
+
+    @Test
+    public void TestImplementStrWithNeedleIsNotPartOfHayStack2(){
+        Integer actual = solution.strStr("1,2,3,4", "3,4,5");
+        Integer expected = -1;
+        assertEquals(actual, expected);
+    }
+
+}
diff --git a/TestRunner.java b/TestRunner.java
new file mode 100644
index 00000000..4fe484a8
--- /dev/null
+++ b/TestRunner.java
@@ -0,0 +1,19 @@
+import com.blankj.hard._025.Solution;
+import com.blankj.hard._025.SolutionTest;
+import com.blankj.structure.ListNode;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+public class TestRunner {
+    public static void main(String[] args) {
+        Result result = JUnitCore.runClasses(SolutionTest.class);
+
+        for (Failure failure : result.getFailures()) {
+            System.out.println(failure.toString());
+        }
+
+        System.out.println(result.wasSuccessful());
+    }
+}
diff --git a/src/com/blankj/structure/ListNode.java b/src/com/blankj/structure/ListNode.java
index dd1588a4..13acea9b 100644
--- a/src/com/blankj/structure/ListNode.java
+++ b/src/com/blankj/structure/ListNode.java
@@ -50,4 +50,19 @@ public static void print(ListNode listNode) {
         }
         System.out.println(str.append("]"));
     }
+
+    public String toString(ListNode listNode) {
+        if (listNode == null) {
+            System.out.println("null");
+            return "";
+        }
+        StringBuilder str = new StringBuilder("[" + String.valueOf(listNode.val));
+        ListNode p = listNode.next;
+        while (p != null) {
+            str.append(",").append(String.valueOf(p.val));
+            p = p.next;
+        }
+        str.append("]");
+        return str.toString();
+    }
 }
diff --git a/src/test/java/com/blankj/hard/_025/SolutionTest.java b/src/test/java/com/blankj/hard/_025/SolutionTest.java
new file mode 100644
index 00000000..124bbede
--- /dev/null
+++ b/src/test/java/com/blankj/hard/_025/SolutionTest.java
@@ -0,0 +1,103 @@
+package com.blankj.hard._025;
+import com.blankj.structure.ListNode;
+import org.hamcrest.CoreMatchers;
+import org.junit.jupiter.api.Test;
+import java.lang.ArithmeticException;
+import java.util.List;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class SolutionTest {
+    Solution solution = new Solution();
+
+    @Test
+    public void TestReverseKGroupsWithHeadNull_1(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[]"), -1);
+        assertNull(actual);
+    }
+
+
+    @Test
+    public void TestReverseKGroupsWithHeadNull_2(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[]"), 0);
+        assertNull(actual);
+    }
+
+
+
+
+    @Test
+    public void TestReverseKGroupsWithHeadNull_3(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[]"), 1);
+        assertNull(actual);
+    }
+
+    @Test
+    public void TestReverseKGroupWith_k_isZero() throws Exception {
+        try {
+            ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), 0);
+            fail("Not throw exception");
+        } catch (Exception e) {
+            assertThat(e, CoreMatchers.instanceOf(ArithmeticException.class));
+            assertEquals(e.getMessage(), "/ by zero");
+        }
+    }
+
+    @Test
+    public void TestReverseKGroupWith_k_isN() throws Exception {
+        try {
+            ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), -1);
+            fail("Not throw exception");
+        } catch (Exception e) {
+            assertThat(e, CoreMatchers.instanceOf(ArithmeticException.class));
+            assertEquals(e.getMessage(), "/ k must greater than 0");
+        }
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), 1);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[1]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_greaterTh(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1]"), 2);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[1]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_isSmThanLengthOfListNode(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1,2,3]"), 2);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[2,1,3]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+    @Test
+    public void TestReverseKGroupsWith_k_isEqualToLength(){
+        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1,2,3]"), 3);
+        String actualString = actual.toString(actual);
+        ListNode expect = ListNode.createTestData("[3,2,1]");
+        String expectString = expect.toString(expect);
+        assertEquals(expectString, actualString);
+    }
+
+//    public static void main(String[] args) {
+//        Solution solution = new Solution();
+//        ListNode actual = solution.reverseKGroup(ListNode.createTestData("[1,2,3,4,5,6,7,8]"), 3);
+//        String actualString = actual.toString(actual);
+//        ListNode expect = ListNode.createTestData("[3,2,1,6,5,4,7,8]");
+//        String expectString = expect.toString(expect);
+//        assertEquals(expectString, actualString);
+//        assert
+//    }
+}
\ No newline at end of file