Best Toxiproxy code snippet using toxics.New
client.go
Source:client.go
...34 ActiveToxics Toxics `json:"toxics"` // The toxics active on this proxy35 client *Client36 created bool // True if this proxy exists on the server37}38// NewClient creates a new client which provides the base of all communication39// with Toxiproxy. Endpoint is the address to the proxy (e.g. localhost:8474 if40// not overriden)41func NewClient(endpoint string) *Client {42 if strings.HasPrefix(endpoint, "https://") {43 log.Fatal("the toxiproxy client does not support https")44 } else if !strings.HasPrefix(endpoint, "http://") {45 endpoint = "http://" + endpoint46 }47 return &Client{endpoint: endpoint}48}49// Proxies returns a map with all the proxies and their toxics.50func (client *Client) Proxies() (map[string]*Proxy, error) {51 resp, err := http.Get(client.endpoint + "/proxies")52 if err != nil {53 return nil, err54 }55 err = checkError(resp, http.StatusOK, "Proxies")56 if err != nil {57 return nil, err58 }59 proxies := make(map[string]*Proxy)60 err = json.NewDecoder(resp.Body).Decode(&proxies)61 if err != nil {62 return nil, err63 }64 for _, proxy := range proxies {65 proxy.client = client66 proxy.created = true67 }68 return proxies, nil69}70// Generates a new uncommitted proxy instance. In order to use the result, the71// proxy fields will need to be set and have `Save()` called.72func (client *Client) NewProxy() *Proxy {73 return &Proxy{74 client: client,75 }76}77// CreateProxy instantiates a new proxy and starts listening on the specified address.78// This is an alias for `NewProxy()` + `proxy.Save()`79func (client *Client) CreateProxy(name, listen, upstream string) (*Proxy, error) {80 proxy := &Proxy{81 Name: name,82 Listen: listen,83 Upstream: upstream,84 Enabled: true,85 client: client,86 }87 err := proxy.Save()88 if err != nil {89 return nil, err90 }91 return proxy, nil92}93// Proxy returns a proxy by name.94func (client *Client) Proxy(name string) (*Proxy, error) {95 // TODO url encode96 resp, err := http.Get(client.endpoint + "/proxies/" + name)97 if err != nil {98 return nil, err99 }100 err = checkError(resp, http.StatusOK, "Proxy")101 if err != nil {102 return nil, err103 }104 proxy := new(Proxy)105 err = json.NewDecoder(resp.Body).Decode(proxy)106 if err != nil {107 return nil, err108 }109 proxy.client = client110 proxy.created = true111 return proxy, nil112}113// Create a list of proxies using a configuration list. If a proxy already exists, it will be replaced114// with the specified configuration. For large amounts of proxies, `config` can be loaded from a file.115// Returns a list of the successfully created proxies.116func (client *Client) Populate(config []Proxy) ([]*Proxy, error) {117 proxies := struct {118 Proxies []*Proxy `json:"proxies"`119 }{}120 request, err := json.Marshal(config)121 if err != nil {122 return nil, err123 }124 resp, err := http.Post(client.endpoint+"/populate", "application/json", bytes.NewReader(request))125 if err != nil {126 return nil, err127 }128 // Response body may need to be read twice, we want to return both the proxy list and any errors129 var body bytes.Buffer130 tee := io.TeeReader(resp.Body, &body)131 err = json.NewDecoder(tee).Decode(&proxies)132 if err != nil {133 return nil, err134 }135 resp.Body = ioutil.NopCloser(&body)136 err = checkError(resp, http.StatusCreated, "Populate")137 return proxies.Proxies, err138}139// Save saves changes to a proxy such as its enabled status or upstream port.140func (proxy *Proxy) Save() error {141 request, err := json.Marshal(proxy)142 if err != nil {143 return err144 }145 var resp *http.Response146 if proxy.created {147 resp, err = http.Post(proxy.client.endpoint+"/proxies/"+proxy.Name, "text/plain", bytes.NewReader(request))148 } else {149 resp, err = http.Post(proxy.client.endpoint+"/proxies", "application/json", bytes.NewReader(request))150 }151 if err != nil {152 return err153 }154 if proxy.created {155 err = checkError(resp, http.StatusOK, "Save")156 } else {157 err = checkError(resp, http.StatusCreated, "Create")158 }159 if err != nil {160 return err161 }162 err = json.NewDecoder(resp.Body).Decode(proxy)163 if err != nil {164 return err165 }166 proxy.created = true167 return nil168}169// Enable a proxy again after it has been disabled.170func (proxy *Proxy) Enable() error {171 proxy.Enabled = true172 return proxy.Save()173}174// Disable a proxy so that no connections can pass through. This will drop all active connections.175func (proxy *Proxy) Disable() error {176 proxy.Enabled = false177 return proxy.Save()178}179// Delete a proxy complete and close all existing connections through it. All information about180// the proxy such as listen port and active toxics will be deleted as well. If you just wish to181// stop and later enable a proxy, use `Enable()` and `Disable()`.182func (proxy *Proxy) Delete() error {183 httpClient := &http.Client{}184 req, err := http.NewRequest("DELETE", proxy.client.endpoint+"/proxies/"+proxy.Name, nil)185 if err != nil {186 return err187 }188 resp, err := httpClient.Do(req)189 if err != nil {190 return err191 }192 return checkError(resp, http.StatusNoContent, "Delete")193}194// Toxics returns a map of all the active toxics and their attributes.195func (proxy *Proxy) Toxics() (Toxics, error) {196 resp, err := http.Get(proxy.client.endpoint + "/proxies/" + proxy.Name + "/toxics")197 if err != nil {198 return nil, err199 }200 err = checkError(resp, http.StatusOK, "Toxics")201 if err != nil {202 return nil, err203 }204 toxics := make(Toxics, 0)205 err = json.NewDecoder(resp.Body).Decode(&toxics)206 if err != nil {207 return nil, err208 }209 return toxics, nil210}211// AddToxic adds a toxic to the given stream direction.212// If a name is not specified, it will default to <type>_<stream>.213// If a stream is not specified, it will default to downstream.214// See https://github.com/Shopify/toxiproxy#toxics for a list of all Toxic types.215func (proxy *Proxy) AddToxic(name, typeName, stream string, toxicity float32, attrs Attributes) (*Toxic, error) {216 toxic := Toxic{name, typeName, stream, toxicity, attrs}217 if toxic.Toxicity == -1 {218 toxic.Toxicity = 1 // Just to be consistent with a toxicity of -1 using the default219 }220 request, err := json.Marshal(&toxic)221 if err != nil {222 return nil, err223 }224 resp, err := http.Post(proxy.client.endpoint+"/proxies/"+proxy.Name+"/toxics", "application/json", bytes.NewReader(request))225 if err != nil {226 return nil, err227 }228 err = checkError(resp, http.StatusOK, "AddToxic")229 if err != nil {230 return nil, err231 }232 result := &Toxic{}233 err = json.NewDecoder(resp.Body).Decode(result)234 if err != nil {235 return nil, err236 }237 return result, nil238}239// UpdateToxic sets the parameters for an existing toxic with the given name.240// If toxicity is set to -1, the current value will be used.241func (proxy *Proxy) UpdateToxic(name string, toxicity float32, attrs Attributes) (*Toxic, error) {242 toxic := map[string]interface{}{243 "attributes": attrs,244 }245 if toxicity != -1 {246 toxic["toxicity"] = toxicity247 }248 request, err := json.Marshal(&toxic)249 if err != nil {250 return nil, err251 }252 resp, err := http.Post(proxy.client.endpoint+"/proxies/"+proxy.Name+"/toxics/"+name, "application/json", bytes.NewReader(request))253 if err != nil {254 return nil, err255 }256 err = checkError(resp, http.StatusOK, "UpdateToxic")257 if err != nil {258 return nil, err259 }260 result := &Toxic{}261 err = json.NewDecoder(resp.Body).Decode(result)262 if err != nil {263 return nil, err264 }265 return result, nil266}267// RemoveToxic renives the toxic with the given name.268func (proxy *Proxy) RemoveToxic(name string) error {269 httpClient := &http.Client{}270 req, err := http.NewRequest("DELETE", proxy.client.endpoint+"/proxies/"+proxy.Name+"/toxics/"+name, nil)271 if err != nil {272 return err273 }274 resp, err := httpClient.Do(req)275 if err != nil {276 return err277 }278 return checkError(resp, http.StatusNoContent, "RemoveToxic")279}280// ResetState resets the state of all proxies and toxics in Toxiproxy.281func (client *Client) ResetState() error {282 resp, err := http.Post(client.endpoint+"/reset", "text/plain", bytes.NewReader([]byte{}))283 if err != nil {284 return err285 }286 return checkError(resp, http.StatusNoContent, "ResetState")287}288type ApiError struct {289 Message string `json:"error"`290 Status int `json:"status"`291}292func (err *ApiError) Error() string {293 return fmt.Sprintf("HTTP %d: %s", err.Status, err.Message)294}295func checkError(resp *http.Response, expectedCode int, caller string) error {296 if resp.StatusCode != expectedCode {297 apiError := new(ApiError)298 err := json.NewDecoder(resp.Body).Decode(apiError)299 if err != nil {300 apiError.Message = fmt.Sprintf("Unexpected response code, expected %d", expectedCode)301 apiError.Status = resp.StatusCode302 }303 return fmt.Errorf("%s: %v", caller, apiError)304 }305 return nil306}...
link_test.go
Source:link_test.go
...13 t.Fatal("No toxics loaded!")14 }15}16func TestStubInitializaation(t *testing.T) {17 collection := NewToxicCollection(nil)18 link := NewToxicLink(nil, collection, stream.Downstream)19 if len(link.stubs) != 1 {20 t.Fatalf("Link created with wrong number of stubs: %d != 1", len(link.stubs))21 } else if cap(link.stubs) != toxics.Count()+1 {22 t.Fatalf("Link created with wrong capacity: %d != %d", cap(link.stubs), toxics.Count()+1)23 } else if cap(link.stubs[0].Input) != 0 {24 t.Fatalf("Noop buffer was not initialized as 0: %d", cap(link.stubs[0].Input))25 } else if cap(link.stubs[0].Output) != 0 {26 t.Fatalf("Link output buffer was not initialized as 0: %d", cap(link.stubs[0].Output))27 }28}29func TestStubInitializaationWithToxics(t *testing.T) {30 collection := NewToxicCollection(nil)31 collection.chainAddToxic(&toxics.ToxicWrapper{32 Toxic: new(toxics.LatencyToxic),33 Type: "latency",34 Direction: stream.Downstream,35 BufferSize: 1024,36 Toxicity: 1,37 })38 collection.chainAddToxic(&toxics.ToxicWrapper{39 Toxic: new(toxics.BandwidthToxic),40 Type: "bandwidth",41 Direction: stream.Downstream,42 Toxicity: 1,43 })44 link := NewToxicLink(nil, collection, stream.Downstream)45 if len(link.stubs) != 3 {46 t.Fatalf("Link created with wrong number of stubs: %d != 3", len(link.stubs))47 } else if cap(link.stubs) != toxics.Count()+1 {48 t.Fatalf("Link created with wrong capacity: %d != %d", cap(link.stubs), toxics.Count()+1)49 } else if cap(link.stubs[len(link.stubs)-1].Output) != 0 {50 t.Fatalf("Link output buffer was not initialized as 0: %d", cap(link.stubs[0].Output))51 }52 for i, toxic := range collection.chain[stream.Downstream] {53 if cap(link.stubs[i].Input) != toxic.BufferSize {54 t.Fatalf("%s buffer was not initialized as %d: %d", toxic.Type, toxic.BufferSize, cap(link.stubs[i].Input))55 }56 }57}58func TestAddRemoveStubs(t *testing.T) {59 collection := NewToxicCollection(nil)60 link := NewToxicLink(nil, collection, stream.Downstream)61 go link.stubs[0].Run(collection.chain[stream.Downstream][0])62 collection.links["test"] = link63 // Add stubs64 collection.chainAddToxic(&toxics.ToxicWrapper{65 Toxic: new(toxics.LatencyToxic),66 Type: "latency",67 Direction: stream.Downstream,68 BufferSize: 1024,69 Toxicity: 1,70 })71 toxic := &toxics.ToxicWrapper{72 Toxic: new(toxics.BandwidthToxic),73 Type: "bandwidth",74 Direction: stream.Downstream,75 BufferSize: 2048,76 Toxicity: 1,77 }78 collection.chainAddToxic(toxic)79 if cap(link.stubs[len(link.stubs)-1].Output) != 0 {80 t.Fatalf("Link output buffer was not initialized as 0: %d", cap(link.stubs[0].Output))81 }82 for i, toxic := range collection.chain[stream.Downstream] {83 if cap(link.stubs[i].Input) != toxic.BufferSize {84 t.Fatalf("%s buffer was not initialized as %d: %d", toxic.Type, toxic.BufferSize, cap(link.stubs[i].Input))85 }86 }87 // Remove stubs88 collection.chainRemoveToxic(toxic)89 if cap(link.stubs[len(link.stubs)-1].Output) != 0 {90 t.Fatalf("Link output buffer was not initialized as 0: %d", cap(link.stubs[0].Output))91 }92 for i, toxic := range collection.chain[stream.Downstream] {93 if cap(link.stubs[i].Input) != toxic.BufferSize {94 t.Fatalf("%s buffer was not initialized as %d: %d", toxic.Type, toxic.BufferSize, cap(link.stubs[i].Input))95 }96 }97}98func TestNoDataDropped(t *testing.T) {99 collection := NewToxicCollection(nil)100 link := NewToxicLink(nil, collection, stream.Downstream)101 go link.stubs[0].Run(collection.chain[stream.Downstream][0])102 collection.links["test"] = link103 toxic := &toxics.ToxicWrapper{104 Toxic: &toxics.LatencyToxic{105 Latency: 1000,106 },107 Type: "latency",108 Direction: stream.Downstream,109 BufferSize: 1024,110 Toxicity: 1,111 }112 done := make(chan struct{})113 defer close(done)114 go func() {115 for i := 0; i < 64*1024; i++ {116 buf := make([]byte, 2)117 binary.BigEndian.PutUint16(buf, uint16(i))118 link.input.Write(buf)119 }120 link.input.Close()121 }()122 go func() {123 for {124 select {125 case <-done:126 return127 default:128 collection.chainAddToxic(toxic)129 collection.chainRemoveToxic(toxic)130 }131 }132 }()133 buf := make([]byte, 2)134 for i := 0; i < 64*1024; i++ {135 n, err := link.output.Read(buf)136 if n != 2 || err != nil {137 t.Fatalf("Read failed: %d %v", n, err)138 } else {139 val := binary.BigEndian.Uint16(buf)140 if val != uint16(i) {141 t.Fatalf("Read incorrect bytes: %v != %d", val, i)142 }143 }144 }145 n, err := link.output.Read(buf)146 if n != 0 || err != io.EOF {147 t.Fatalf("Expected EOF: %d %v", n, err)148 }149}150func TestToxicity(t *testing.T) {151 collection := NewToxicCollection(nil)152 link := NewToxicLink(nil, collection, stream.Downstream)153 go link.stubs[0].Run(collection.chain[stream.Downstream][0])154 collection.links["test"] = link155 toxic := &toxics.ToxicWrapper{156 Toxic: new(toxics.TimeoutToxic),157 Name: "timeout1",158 Type: "timeout",159 Direction: stream.Downstream,160 Toxicity: 0,161 }162 collection.chainAddToxic(toxic)163 // Toxic should be a Noop because of toxicity164 n, err := link.input.Write([]byte{42})165 if n != 1 || err != nil {166 t.Fatalf("Write failed: %d %v", n, err)167 }168 buf := make([]byte, 2)169 n, err = link.output.Read(buf)170 if n != 1 || err != nil {171 t.Fatalf("Read failed: %d %v", n, err)172 } else if buf[0] != 42 {173 t.Fatalf("Read wrong byte: %x", buf[0])174 }175 toxic.Toxicity = 1176 toxic.Toxic.(*toxics.TimeoutToxic).Timeout = 100177 collection.chainUpdateToxic(toxic)178 err = testhelper.TimeoutAfter(150*time.Millisecond, func() {179 n, err = link.input.Write([]byte{42})180 if n != 1 || err != nil {181 t.Fatalf("Write failed: %d %v", n, err)182 }183 n, err = link.output.Read(buf)184 if n != 0 || err != io.EOF {185 t.Fatalf("Read did not get EOF: %d %v", n, err)186 }187 })188 if err != nil {189 t.Fatal(err)190 }191}192func TestStateCreated(t *testing.T) {193 collection := NewToxicCollection(nil)194 link := NewToxicLink(nil, collection, stream.Downstream)195 go link.stubs[0].Run(collection.chain[stream.Downstream][0])196 collection.links["test"] = link197 collection.chainAddToxic(&toxics.ToxicWrapper{198 Toxic: new(toxics.LimitDataToxic),199 Type: "limit_data",200 Direction: stream.Downstream,201 Toxicity: 1,202 })203 if link.stubs[len(link.stubs)-1].State == nil {204 t.Fatalf("New toxic did not have state object created.")205 }206}...
helper_toxi_test.go
Source:helper_toxi_test.go
...33 if err != nil {34 msg := fmt.Sprintf("Failed to marshal toxic for api (1): %v", toxic)35 panic(msg)36 }37 return bytes.NewReader(request)38}39// Available type name40// - noop41// - slicer42// - timeout43// - bandwidth44// - latency45// - limit_data46func getToxicType(tx toxics.Toxic) string {47 switch tx.(type) {48 case *toxics.NoopToxic:49 return "noop"50 case *toxics.SlicerToxic:51 return "slicer"52 case *toxics.TimeoutToxic:53 return "timeout"54 case *toxics.BandwidthToxic:55 return "bandwidth"56 case *toxics.LatencyToxic:57 return "latency"58 case *toxics.LimitDataToxic:59 return "limit_data"60 default:61 panic("Unknown toxic type")62 }63}64func getStreamDirect(stream string) string {65 tmp := strings.ToLower(stream)66 if strings.HasPrefix(tmp, "down") {67 return "downstream"68 }69 return "upstream"70}71func NewTestProxy(name, upstream string) *toxiproxy.Proxy {72 proxy := toxiproxy.NewProxy()73 proxy.Name = name74 proxy.Listen = "localhost:0"75 proxy.Upstream = upstream76 return proxy77}78type ToxicOptions struct {79 Name string80 Stream string // upstream/downstream81 Toxic toxics.Toxic82}83func toxicToReader(opts ToxicOptions) io.Reader {84 toxicType := getToxicType(opts.Toxic)85 direct := getStreamDirect(opts.Stream)86 return ToxicToJson(opts.Name, toxicType, direct, opts.Toxic)87}88func newTestProxyWithToxic(name, upstream string, opts ToxicOptions) *toxiproxy.Proxy {89 proxy := NewTestProxy(name, upstream)90 proxy.Start()91 // defer proxy.Stop()92 if opts.Toxic == nil {93 return proxy94 }95 reader := toxicToReader(opts)96 _, err := proxy.Toxics.AddToxicJson(reader)97 if err != nil {98 panic(err)99 }100 return proxy101}102func newTestClientViaProxy(clientOpts ClientOptions, txOpts ToxicOptions) (*toxiproxy.Proxy, pulsar.Client) {103 proxy := newTestProxyWithToxic("pulsar-proxy",104 "localhost:6650", txOpts)105 client, err := pulsar.NewClient(pulsar.ClientOptions{106 URL: fmt.Sprintf("pulsar://%s", proxy.Listen),107 ConnectionTimeout: clientOpts.DialTimeout,108 OperationTimeout: clientOpts.OpTimeout,109 })110 if err != nil {111 panic(err)112 }113 return proxy, client114}115// update or add toxic116// FIXME: not work, only for same type117func updateProxyToxic(proxy *toxiproxy.Proxy, opts ToxicOptions) {118 var err error119 defer func() {...
New
Using AI Code Generation
1import (2func main() {3 client := toxiproxy.NewClient("localhost:8474")4 toxics, err := client.Toxics("redis")5 if err != nil {6 panic(err)7 }8 fmt.Println(toxics)9}10import (11func main() {12 client := toxiproxy.NewClient("localhost:8474")13 toxics, err := client.Toxics("redis")14 if err != nil {15 panic(err)16 }17 toxic := toxiproxy.Toxic{18 Attributes: map[string]interface{}{19 },20 }21 err = toxics.Add("latency", toxic)22 if err != nil {23 panic(err)24 }25 fmt.Println(toxics)26}27main.main()28main.main()29import (30func main() {
New
Using AI Code Generation
1import (2func main() {3 toxic := client.Toxic{4 Attributes: client.Attributes{5 },6 }7 toxics, _ := client.NewToxics("localhost:8474", "redis")8 err := toxics.Create(&toxic)9 if err != nil {10 fmt.Println(err)11 }12}13import (14func main() {15 toxic := client.Toxic{16 Attributes: client.Attributes{17 },18 }19 toxics, _ := client.NewToxics("localhost:8474", "redis")20 err := toxics.Create(&toxic)21 if err != nil {22 fmt.Println(err)23 }24}25import (26func main() {27 toxic := client.Toxic{28 Attributes: client.Attributes{29 },30 }31 toxics, _ := client.NewToxics("localhost:8474", "redis")32 err := toxics.Create(&toxic)33 if err != nil {34 fmt.Println(err)35 }36}37import (38func main() {39 toxic := client.Toxic{
New
Using AI Code Generation
1import (2func main() {3 toxics, err := client.NewToxics("localhost:8474", "test")4 if err != nil {5 fmt.Println("Error creating toxics")6 }7 toxic := toxics.New("latency", "downstream", 1.0)8 toxic.Save()9}10import (11func main() {12 toxics, err := client.NewToxics("localhost:8474", "test")13 if err != nil {14 fmt.Println("Error creating toxics")15 }16 toxic := toxics.Add("latency", "downstream", 1.0)17 toxic.Save()18}19import (20func main() {21 toxic, err := client.NewToxic("localhost:8474", "test", "latency_downstream")22 if err != nil {23 fmt.Println("Error creating toxic")24 }25 toxic.Save()26}27import (28func main() {29 toxic, err := client.NewToxic("localhost:8474", "test", "latency_downstream")30 if err != nil {31 fmt.Println("Error creating toxic")32 }
New
Using AI Code Generation
1import (2func main() {3 toxics := client.Toxics{4 Attributes: map[string]string{5 },6 }7 toxics.New()8 fmt.Println(toxics)9}10import (11func main() {12 proxies := client.Proxies{
New
Using AI Code Generation
1toxics := toxiproxy.NewToxics()2toxic := toxiproxy.NewToxic()3toxic := toxiproxy.NewToxic()4toxics := toxiproxy.NewToxics()5toxic := toxiproxy.NewToxic()6toxic := toxiproxy.NewToxic()7toxics := toxiproxy.NewToxics()8toxic := toxiproxy.NewToxic()9toxic := toxiproxy.NewToxic()10toxics := toxiproxy.NewToxics()11toxic := toxiproxy.NewToxic()12toxic := toxiproxy.NewToxic()13toxics := toxiproxy.NewToxics()14toxic := toxiproxy.NewToxic()15toxic := toxiproxy.NewToxic()16toxics := toxiproxy.NewToxics()17toxic := toxiproxy.NewToxic()18toxic := toxiproxy.NewToxic()19toxics := toxiproxy.NewToxics()20toxic := toxiproxy.NewToxic()21toxic := toxiproxy.NewToxic()
New
Using AI Code Generation
1import (2func main() {3 toxics := toxiproxy.NewToxics()4 toxics.Add("toxic1", toxiproxy.Toxic{5 Attributes: map[string]interface{}{6 },7 })8 fmt.Println(toxics)9}10{map[toxic1:{latency downstream 1 map[latency:1000 jitter:0]}]}11cannot use toxiproxy.Toxic literal (type toxiproxy.Toxic) as type *toxiproxy.Toxic in argument to toxics.Add12toxics.Add("toxic1", &toxiproxy.Toxic{13 Attributes: map[string]interface{}{14 },15})16toxic := &toxiproxy.Toxic{17 Attributes: map[string]interface{}{18 },19}20toxics.Add("toxic1", toxic)21toxics.Add("toxic1", &toxiproxy.Toxic{22 Attributes: map[string]interface{}{23 },24})
New
Using AI Code Generation
1func main() {2 toxics := ToxiproxyClient.New("localhost", 8474)3 toxics.Add("myproxy", "latency", "downstream", 5000, 0.0)4 toxics.Add("myproxy", "bandwidth", "upstream", 10000, 0.0)5}6func main() {7 toxics := toxiproxy.New("localhost", 8474)8 toxics.Add("myproxy", "latency", "downstream", 5000, 0.0)9 toxics.Add("myproxy", "bandwidth", "upstream", 10000, 0.0)10}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!