Prueba una integración de CAPTCHA en Go sin gastar crédito

Por solvethree4 min de lectura

Apunta el SDK oficial de Go a un servidor httptest mediante NewClientWithBaseURL. El servidor proporciona las respuestas de las tareas, por lo que puedes probar el SDK sin gastar crédito de solvethree ni proporcionar secretos de la aplicación.

En esta página

Ejecutar el SDK con un entorno de prueba local

  1. 1.

    Instala la dependencia

    Usa Go 1.22 o posterior. En tu módulo de Go, usa go get para instalar solvethree.com/[email protected]. El módulo se sirve desde solvethree.com.

  2. 2.

    Guardar y ejecutar la prueba

    Guarda el ejemplo como captcha_integration_test.go en un directorio exclusivo para pruebas dentro de tu módulo y ejecuta go test desde ese directorio. No cambies la clave, el nombre de host ni el proxy del entorno de prueba: son datos de prueba, no credenciales ni servicios que debas configurar.

Go · una prueba de integración aislada del SDK
package integration_test

import (
    "context"
    "fmt"
    "net/http"
    "net/http/httptest"
    "sync/atomic"
    "testing"
    "time"
    solvethree "solvethree.com/sdk"
)

func TestSolve(t *testing.T) {
    var posts atomic.Int32
    server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        if r.Method == "POST" {
            posts.Add(1)
            fmt.Fprint(w, `{"id":"fixture-1","status":"pending"}`)
            return
        }
        fmt.Fprint(w, `{"id":"fixture-1","status":"ready","solution":{"token":"FIXTURE_TOKEN","userAgent":"fixture-browser-identity","secChUa":"fixture-hints"}}`)
    }))
    defer server.Close()
    client, err := solvethree.NewClientWithBaseURL("fixture-key", server.URL, nil)
    if err != nil { t.Fatal(err) }
    result, err := client.Solve(context.Background(), solvethree.TaskRequest{
        Site: "accounts.example.com", Action: "login", Proxy: "http://proxy.example:8080",
    }, solvethree.SolveOptions{Timeout: time.Second, PollInterval: time.Millisecond})
    if err != nil { t.Fatal(err) }
    if result.Solution.Token != "FIXTURE_TOKEN" || posts.Load() != 1 { t.Fatal("incorrect lifecycle") }
}

NewClientWithBaseURL acepta HTTP de bucle local para las pruebas. Aquí, server.URL sustituye la dirección de la API de producción y el manejador responde localmente. El valor del proxy solo forma parte de la tarea enviada; este entorno de prueba no se conecta a él.

Qué demuestra que la prueba pase

La respuesta al POST deja la tarea pendiente. Una solicitud posterior recibe una respuesta de tarea lista que contiene FIXTURE_TOKEN. La aserción final comprueba tanto el token devuelto como que se haya realizado exactamente un POST, lo que permite detectar la creación accidental de una tarea adicional durante este flujo.

El manejador es deliberadamente sencillo: toda solicitud que no sea POST recibe la respuesta de tarea lista. No comprueba el método de sondeo, la ruta de la solicitud ni el JSON enviado. Para probar también el contrato de las solicitudes, haz que el manejador compruebe las rutas esperadas de creación y recuperación de tareas, además del sitio, la acción y el proxy enviados.

Que esta prueba pase demuestra que el ciclo de vida simulado del SDK funciona. No valida un perfil de sitio real, un proxy ni la aceptación del token por parte del destino. El token y la identidad del navegador devueltos son valores de prueba.

Añadir casos de fallo donde tu integración toma decisiones

Amplía el manejador local para que devuelva las condiciones que tu aplicación debe gestionar. Mantén el contador de POST: reintentar un sondeo no debería crear otra tarea.

Casos de prueba adicionales, no cubiertos por el ejemplo anterior
Casos de prueba adicionales, no cubiertos por el ejemplo anterior
Comportamiento del entorno de pruebaQué comprobar
Una solicitud de sondeo devuelve HTTP 429, 502, 503 o 504 y, después, una respuesta de tarea lista.Solve reintenta los fallos temporales de sondeo, respeta Retry-After dentro del plazo y sigue enviando un solo POST.
La tarea pasa al estado fallido con errorCode site-unreachable y un mensaje de error.Gestiona *solvethree.TaskFailedError y deja de sondear esa tarea. Su ErrorCode identifica el fallo; recupera la tarea fallida cuando necesites el texto de Error.
La creación devuelve una respuesta HTTP no satisfactoria.Gestiona el error HTTP en lugar de tratar la respuesta como una tarea creada correctamente. Usa errors.As para extraer *solvethree.APIError e inspeccionar StatusCode.
La tarea permanece pendiente hasta que vence el plazo.Detecta context.DeadlineExceeded con errors.Is. Un tiempo de espera agotado pone fin a la espera; no cancela el trabajo remoto.
El servidor registra la creación, pero el cliente pierde la respuesta.Comprueba la información de recuperación en *solvethree.Error. CreateTask no reintenta POST automáticamente. Recupera la tarea con GetTask si conoces TaskID, o vuelve a enviar exactamente los datos originales con el mismo RequestID.

Para el caso de pérdida de la respuesta, asigna a la prueba un ID de solicitud explícito y haz que el entorno de prueba devuelva la tarea existente cuando se vuelvan a enviar ese ID y los mismos datos. De lo contrario, estarás probando una segunda creación, no una recuperación.

Ejecuta tu primera tarea.

Empieza con $5 de crédito en tu espacio de trabajo.

Crear un espacio de trabajo
Prueba una integración de CAPTCHA en Go sin gastar crédito · solvethree