github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/tests/mq_protocol_tests/README.md (about)

     1  # Integration Framework
     2  
     3  ## Introduction
     4  The **Integration Framework** is designed to provide a flexible way for contributors to write integration tests for new
     5  sinks or MQ protocols. The core of the framework is stored in `{ticdc_root}/tests/mq_protocol_tests/framework`, and test
     6  cases should be stored in `{ticdc_root}/tests/mq_protocol_tests/cases`. Currently, although the Framework is still under
     7  active development, it is capable of helping test Avro support and it is the only officially supported way for
     8  developers to run integration tests with Kafka connect.
     9  
    10  ## Quick Start
    11  To create a test case, you need to:
    12  - create a struct that implements the `Task` interface,
    13  - and ask the Environment to run the task in the `main` function in `integration.go`.
    14  Note that the second step will be automated soon.
    15  
    16  ```go
    17  // Task represents a single test case
    18  type Task interface {
    19  	Name() string
    20  	GetCDCProfile() *CDCProfile
    21  	Prepare(taskContext *TaskContext) error
    22  	Run(taskContext *TaskContext) error
    23  }
    24  ```
    25  For the time being, if you would like to write a test case for Avro and Canal, it is recommended to write a base case which define the common operations of test, and write construct function, pass `canal.SingleTableTask` or `canal.SingleTableTask` as parameters, which execute the necessary setup steps, including creating the Kafka Connect sink and creating the changefeed with appropriate configurations. 
    26  
    27  
    28  Example:
    29  ```go
    30  // cases/base_mycase.go
    31  type MyCase struct {
    32  	framework.Task
    33  }
    34  
    35  func NewMyCase(task framework) *MyCase{
    36  	return &MyCase{
    37          Task: task,  
    38      }   
    39  }
    40  
    41  func (c *MyCase) Name() string {
    42  	return "My Case"
    43  }
    44  
    45  func (c *MyCase) Run(ctx *framework.TaskContext) error {
    46  	_, err := ctx.Upstream.ExecContext(ctx.Ctx, "create table test (id int primary key, value int)")
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	// Get a handle of an existing table
    52  	table := ctx.SQLHelper().GetTable("test")
    53  	// Create an SQL request, send it to the upstream, wait for completion and check the correctness of replication
    54  	err = table.Insert(map[string]interface{}{
    55  		"id":    0,
    56  		"value": 0,
    57  	}).Send().Wait().Check()
    58  	if err != nil {
    59  		return errors.AddStack(err)
    60  	}
    61  
    62  	// To wait on a batch of SQL requests, create a slice of Awaitables
    63  	reqs := make([]framework.Awaitable, 0)
    64  	for i := 1; i < 1000; i++ {
    65  		// Only send, do not wait
    66  		req := table.Insert(map[string]interface{}{
    67  			"id":    i,
    68  			"value": i,
    69  		}).Send()
    70  		reqs = append(reqs, req)
    71  	}
    72  
    73  	// Wait on SQL requests in batch and check the correctness
    74  	return framework.All(ctx.SQLHelper(), reqs).Wait().Check()
    75  }
    76  
    77  
    78  // main.go
    79  func main() {
    80      task := &canal.SingleTableTask{TableName: "test"}
    81      testCases := []framework.Task{
    82          tests.NewMyCase(task),
    83      }
    84      task := &avro.SingleTableTask{TableName: "test"}
    85      testCases := []framework.Task{
    86          tests.NewMyCase(task),
    87      }
    88      //run
    89  }
    90  ```