mikespook/gearman-go

Creating jobs for testing purposes

Closed this issue · 6 comments

I'm new to Go, so apologies if this is super-obvious.

I'm writing a Gearman worker using this library; I want to be able to test my functions, but I can't quite figure out how to create a test job to pass in to the method that actually does the processing.

Just as my super-basic example for now:

func DisplayMessage(job worker.Job) ([]byte, error) {
	log.Printf("DisplayMessage: Data=[%s]\n", job.Data())
	data := []byte(strings.ToUpper(string(job.Data())))
	return data, nil
}

I can see that I need to pass a struct of type worker.Job, but I can't figure out how to create that struct.

I guess if I needed to, I could use the client to send a job directly to Gearman, but I'd rather minimise the number of moving parts here. I couldn't see a test in the library that created jobs (but again, I might have missed that).

Can anyone help?

I think I've figured this out now, though not necessarily in the best way. Here's my test script:

package main

import (
	"testing"
	"github.com/mikespook/gearman-go/worker"
	"crypto/sha256"
)

type TestJob struct {
	JobHandle string
	JobId string
	JobData string
}

func (tj TestJob) Err() error {
	return nil
}

func (tj TestJob) Data() []byte {
	return []byte(tj.JobData)
}

func (tj TestJob) Fn() string {
	return "TestJob"
}

func (tj TestJob) SendWarning(data []byte) {
	// NOOP
}

func (tj TestJob) SendData(data []byte) {
	// NOOP
}

func (tj TestJob) UpdateStatus(numerator, denominator int) {
	// NOOP
}

func (tj TestJob) Handle() string {
	return tj.JobHandle
}

func (tj TestJob) UniqueId() string {
	return tj.JobId
}

func createJob(data []byte) (job worker.Job, err error) {
	hasher := sha256.New()
	hasher.Write(data)
	jobHandle := string(hasher.Sum(nil))

	jobData := string(data)

	jobId := jobHandle[0:16]

	newJob := TestJob{JobId: jobId, JobHandle: jobHandle, JobData: jobData}

	return newJob, nil
}

func TestDisplayMessage(t *testing.T) {
	expected := "HELLO"

	job, err := createJob([]byte("Hello"))
	if err != nil {
		t.Error("Couldn't create the job.")
	}

	actual, err := DisplayMessage(job)
	if string(actual) != expected {
		t.Errorf("Expected '%s', got '%s'", expected, string(actual))
	}
}

Is there an easier way to get to this? :)

It's not about "new to go", but "new to programing" ?
you don't need to call the func DisplayMessage,so you don't need make a Job, it's a callback function, just register (see https://github.com/mikespook/gearman-go/blob/master/example/worker/worker.go)
then send a command on another PC by Client.go to the gearman-server. if worker is running and is connected to the server,it could received the msg and call the func DisplayMessage

I think this project is dead .. no udpating, no issue closing

Hi @stevehill1981
You can't test the worker directly unless you write your own dummy-job and pass it to the callback.

But if you want to combine the testing of client and worker, you need Gearman server involved in.

It's not a good practical thing, isn't it? So, I abandoned Gearman from the architecture of my projects.

Hi @lanybass

Dying, but not dead.

The Gearman protocol has some bad design inside and personally, I've used MQTT to replace Gearman recent years.

The issue will keep open unless I think we have all the facts we need. Still, I will try to fix the significant issue but won't improve the library.

And If someone can relive this project, I'd like to transfer the project (or just make a clone and let me know).

Thanks @mikespook. I'm stuck with Gearman for the time being for legacy reasons, but perhaps, if I'm rewriting the workers anyway (moving from PHP to Go), I can justify changing the queueing system at the same time.

@lanybass - I wanted to test just the functionality of DisplayMessage; not the Gearman worker part of it. I'm coming from the PHP world (which may or may not make me a proper programmer, despite more than 10 years of experience), and when I was doing a similar thing there I had to extend the GearmanJob class so that I could set the appropriate data without having to run a full client/server setup. Apologies if this doesn't give me street cred as a real programmer.

I would highly recommend abstracting the functionality you use gearman for in your project to an interface. This way you can mock the gearman functionality in a unit test. Anything involving the actual gearman worker would be an integration test.

For this specific case you can just create a mock struct. You can see the structure you need for it here: https://github.com/mikespook/gearman-go/blob/master/worker/job.go