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