How to use getActualType method of org.evomaster.client.java.controller.problem.rpc.RPCEndpointsBuilder class

Best EvoMaster code snippet using org.evomaster.client.java.controller.problem.rpc.RPCEndpointsBuilder.getActualType

Source:RPCEndpointsBuilder.java Github

copy

Full Screen

...401 namedValue = new ByteBufferParam(name, accessibleSchema);402 } else if (List.class.isAssignableFrom(clazz) || Set.class.isAssignableFrom(clazz)){403 if (genericType == null)404 throw new RuntimeException("genericType should not be null for List and Set class");405 Type type = ((ParameterizedType) genericType).getActualTypeArguments()[0];406 Class<?> templateClazz = getTemplateClass(type, genericTypeMap);407 NamedTypedValue template = build(schema, templateClazz, type,"template", rpcType, depth, customizationDtos, relatedCustomization, null, notNullAnnotations, null, genericTypeMap);408 template.setNullable(false);409 CollectionType ctype = new CollectionType(clazz.getSimpleName(),clazz.getName(), template, clazz);410 ctype.depth = getDepthLevel(clazz, depth, clazzWithGenericTypes);411 if (List.class.isAssignableFrom(clazz))412 namedValue = new ListParam(name, ctype, accessibleSchema);413 else414 namedValue = new SetParam(name, ctype, accessibleSchema);415 } else if (Map.class.isAssignableFrom(clazz)){416 if (genericType == null)417 throw new RuntimeException("genericType should not be null for List and Set class");418 Type keyType = ((ParameterizedType) genericType).getActualTypeArguments()[0];419 Type valueType = ((ParameterizedType) genericType).getActualTypeArguments()[1];420 Class<?> keyTemplateClazz = getTemplateClass(keyType, genericTypeMap);421 NamedTypedValue keyTemplate = build(schema, keyTemplateClazz, keyType,"keyTemplate", rpcType, depth, customizationDtos, relatedCustomization, null, notNullAnnotations, null, genericTypeMap);422 keyTemplate.setNullable(false);423 Class<?> valueTemplateClazz = getTemplateClass(valueType, genericTypeMap);424 NamedTypedValue valueTemplate = build(schema, valueTemplateClazz, valueType,"valueTemplate", rpcType, depth, customizationDtos, relatedCustomization, null, notNullAnnotations, null, genericTypeMap);425 MapType mtype = new MapType(clazz.getSimpleName(), clazz.getName(), new PairParam(new PairType(keyTemplate, valueTemplate), null), clazz);426 mtype.depth = getDepthLevel(clazz, depth, clazzWithGenericTypes);427 namedValue = new MapParam(name, mtype, accessibleSchema);428 } else if (Date.class.isAssignableFrom(clazz)){429 if (clazz == Date.class)430 namedValue = new DateParam(name, accessibleSchema);431 else432 throw new RuntimeException("NOT support "+clazz.getName()+" date type in java yet");433 } else if (Exception.class.isAssignableFrom(clazz) && clazz.getName().startsWith("java")){434 // note that here we only extract class name and message435 StringParam msgField = new StringParam("message", new AccessibleSchema(false, null, "getMessage"));436 ObjectType exceptionType = new ObjectType(clazz.getSimpleName(), clazz.getName(), Collections.singletonList(msgField), clazz, genericTypes);437 namedValue = new ObjectParam(name, exceptionType, accessibleSchema);438 } else {439 if (clazz.getName().startsWith("java")){440 throw new RuntimeException("NOT handle "+clazz.getName()+" class in java yet");441 }442 long cycleSize = depth.stream().filter(s-> s.equals(getObjectTypeNameWithFlag(clazz, clazzWithGenericTypes))).count();443 if (cycleSize == 1){444 List<NamedTypedValue> fields = new ArrayList<>();445 Map<Integer, CustomizedRequestValueDto> objRelatedCustomizationDtos = getCustomizationBasedOnSpecifiedType(customizationDtos, clazz.getName());446 // field list447 List<Field> fieldList = new ArrayList<>();448 getAllFields(clazz, fieldList, rpcType);449 for(Field f: fieldList){450 // skip final field451 if (Modifier.isFinal(f.getModifiers()))452 continue;453 if (doSkipReflection(f.getName()))454 continue;455 AccessibleSchema faccessSchema = null;456 //check accessible457 if (Modifier.isPublic(f.getModifiers())){458 faccessSchema = new AccessibleSchema();459 } else{460 // find getter and setter461 faccessSchema = new AccessibleSchema(false, findGetterOrSetter(clazz, f, false), findGetterOrSetter(clazz, f, true));462 if (faccessSchema.getterMethodName == null || faccessSchema.setterMethodName == null){463 SimpleLogger.warn("Error: skip the field "+f.getName()+" since its setter/getter is not found");464 continue;465 }466 }467 Class<?> fType = f.getType();468 Class<?> foriginalType = null;469 Type fGType = f.getGenericType();470 if (f.getGenericType() instanceof TypeVariable){471 foriginalType = f.getType();472 Type actualType = getActualType(genericTypeMap, (TypeVariable) f.getGenericType());473 if (actualType instanceof Class){474 fType = (Class<?>) actualType;475 fGType = fType;476 }else if (actualType instanceof ParameterizedType){477 fGType = actualType;478 if (((ParameterizedType) actualType).getRawType() instanceof Class<?>)479 fType = (Class<?>) ((ParameterizedType) actualType).getRawType();480 else481 throw new RuntimeException("Error: Fail to handle actual type of a generic type");482 }483 }484 NamedTypedValue field = build(schema, fType, fGType,f.getName(), rpcType, depth, objRelatedCustomizationDtos, relatedCustomization, faccessSchema, notNullAnnotations, foriginalType, genericTypeMap);485 for (Annotation annotation : f.getAnnotations()){486 handleConstraint(field, annotation, notNullAnnotations);487 }488 fields.add(field);489 }490 handleNativeRPCConstraints(clazz, fields, rpcType);491 ObjectType otype = new ObjectType(clazz.getSimpleName(), clazz.getName(), fields, clazz, genericTypes);492 otype.setOriginalType(originalType);493 otype.depth = getDepthLevel(clazz, depth, clazzWithGenericTypes);494 ObjectParam oparam = new ObjectParam(name, otype, accessibleSchema);495 schema.registerType(otype.copy(), oparam);496 namedValue = oparam;497 }else {498 CycleObjectType otype = new CycleObjectType(clazz.getSimpleName(), clazz.getName(), clazz, genericTypes);499 otype.depth = getDepthLevel(clazz, depth, clazzWithGenericTypes);500 ObjectParam oparam = new ObjectParam(name, otype, accessibleSchema);501 schema.registerType(otype.copy(), oparam);502 namedValue = oparam;503 }504 }505 }catch (ClassCastException e){506 throw new RuntimeException(String.format("fail to perform reflection on param/field: %s; class: %s; genericType: %s; class of genericType: %s; depth: %s; error info:%s",507 name, clazz.getName(), genericType==null?"null":genericType.getTypeName(), genericType==null?"null":genericType.getClass().getName(), String.join(",", depth), e.getMessage()));508 }509 namedValue.getType().setOriginalType(originalType);510 if (customizationDtos!=null){511 handleNamedValueWithCustomizedDto(namedValue, customizationDtos, relatedCustomization);512 }513 return namedValue;514 }515 private static String getNameEnumConstant(Object object) {516 try {517 Method name = object.getClass().getMethod("name");518 name.setAccessible(true);519 return (String) name.invoke(object);520 } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {521 SimpleLogger.warn("Driver Error: fail to extract name for enum constant", e);522 return object.toString();523 }524 }525 private static void handleGenericSuperclass(Class clazz, Map<TypeVariable, Type> map){526 if (isNotCustomizedObject(clazz)) return;527 if (clazz.getGenericSuperclass() == null || !(clazz.getGenericSuperclass() instanceof ParameterizedType)) return;528 Type[] actualTypes = ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments();529 if (((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments().length == 0) return;530 TypeVariable[] typeVariables = clazz.getSuperclass().getTypeParameters();531 if (typeVariables.length != actualTypes.length){532 throw new RuntimeException("Error: fail to handle generic types in Dto");533 }534 for (int i = 0; i < typeVariables.length; i++){535 map.put(typeVariables[i], actualTypes[i]);536 }537 handleGenericSuperclass(clazz.getSuperclass(), map);538 }539 private static List<String> handleGenericType(Class<?> clazz, Type genericType, Map<TypeVariable, Type> map){540 if (isNotCustomizedObject(clazz)) return null;541 if (!(genericType instanceof ParameterizedType)) return null;542 List<String> genericTypes = new ArrayList<>();543 Type[] actualTypes = ((ParameterizedType) genericType).getActualTypeArguments();544 TypeVariable[] typeVariables = clazz.getTypeParameters();545 if (typeVariables.length != actualTypes.length){546 throw new RuntimeException("Error: fail to handle generic types in Dto");547 }548 for (int i = 0; i < typeVariables.length; i++){549 Type a = actualTypes[i];550 if (a instanceof TypeVariable)551 a = getActualType(map, (TypeVariable) a);552 if (a != null)553 genericTypes.add(a.getTypeName());554 map.put(typeVariables[i], actualTypes[i]);555 }556 return genericTypes;557 }558 private static Type getActualType(Map<TypeVariable, Type> map, TypeVariable typeVariable){559 Type t = map.get(typeVariable);560 if (t == null) return null;561 if (t instanceof TypeVariable)562 return getActualType(map, (TypeVariable) t);563 return t;564 }565 private static void getAllFields(Class<?> clazz, List<Field> fieldList, RPCType type){566 if (type == RPCType.THRIFT && isNativeThriftDto(clazz)){567 getFieldForNativeThriftDto(clazz, fieldList);568 return;569 }570 fieldList.addAll(0, Arrays.asList(clazz.getDeclaredFields()));571 if (!Exception.class.isAssignableFrom(clazz) && clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class)572 getAllFields(clazz.getSuperclass(), fieldList, type);573 }574 private static Map<Integer, CustomizedRequestValueDto> getCustomizationBasedOnSpecifiedType(Map<Integer, CustomizedRequestValueDto> customizationDtos, String objTypeName){575 if (customizationDtos == null) return null;576 return customizationDtos.entrySet().stream().filter(s-> s.getValue().specificRequestTypeName == null ||577 s.getValue().specificRequestTypeName.equals(objTypeName)).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));578 }579 private static String findGetterOrSetter(Class<?> clazz, Field field, boolean findGetter){580 List<Method> found;581 if (findGetter){582 found = Arrays.stream(clazz.getMethods()).filter(m->583 Modifier.isPublic(m.getModifiers()) &&584// (m.getName().equalsIgnoreCase("get"+field.getName()) || m.getName().equalsIgnoreCase("is"+field.getName())) &&585 isGetter(field.getName(), m.getName(), field.getType().getTypeName()) &&586 m.getParameterCount() == 0587 ).collect(Collectors.toList());588 }else {589 found = Arrays.stream(clazz.getMethods()).filter(m->590 Modifier.isPublic(m.getModifiers()) &&591// m.getName().equalsIgnoreCase("set"+field.getName()) &&592 isSetter(field.getName(), m.getName(), field.getType().getTypeName()) &&593 m.getParameterCount() == 1 &&594 (m.getParameterTypes()[0].equals(field.getType()) || m.getParameterTypes()[0].equals(PrimitiveOrWrapperParam.getPrimitiveOrWrapper(field.getType())))595 ).collect(Collectors.toList());596 }597 if (found.size() == 1)598 return found.get(0).getName();599 String msg = "RPC extract schema Error: cannot access field property, there exist "+found.size()+" methods to access the field "+ field.getName() + " for the class "+ clazz.getName();600 if (found.size() > 1){601 /*602 instead of throwing the exception,603 provide a warning and use the first one604 */605 SimpleLogger.uniqueWarn(msg);606 return found.get(0).getName();607 }608 SimpleLogger.uniqueWarn(msg);609 return null;610 }611 private static boolean isSetter(String fieldName, String methodName, String type){612 boolean isBoolean = type.equals(Boolean.class.getName()) || type.equals(boolean.class.getName());613 String fieldText = fieldName;614 if (isBoolean && fieldText.startsWith("is") && fieldText.length() > 2)615 fieldText = fieldText.substring(2);616 String gsMethod = "set";617 return methodName.equalsIgnoreCase(gsMethod+fieldText) || methodName.equalsIgnoreCase(gsMethod+fieldName);618 }619 private static boolean isGetter(String fieldName, String methodName, String type){620 boolean isBoolean = type.equals(Boolean.class.getName()) || type.equals(boolean.class.getName());621 return methodName.equalsIgnoreCase("get"+fieldName) || (isBoolean && (methodName.equalsIgnoreCase(fieldName) || methodName.equalsIgnoreCase("is"+fieldName)));622 }623 private static void handleNamedValueWithCustomizedDto(NamedTypedValue namedTypedValue, Map<Integer, CustomizedRequestValueDto> customizationDtos, Set<String> relatedCustomization){624 List<String> candidateReferences = new ArrayList<>();625 List<NamedTypedValue> candidates = new ArrayList<>();626 customizationDtos.forEach((i, dto)->{627 if (dto.combinedKeyValuePairs != null628 // && (dto.specificRequestTypeName == null || dto.specificRequestTypeName.equals(namedTypedValue.getType().getFullTypeName()))629 ){630 dto.combinedKeyValuePairs.forEach(p->{631 if (p.fieldKey.equals(namedTypedValue.getName())){632 NamedTypedValue copy = namedTypedValue.copyStructureWithProperties();633 boolean ok = setNamedValueBasedOnCandidates(copy, p.fieldValue);634 if (ok){635 if (!candidateReferences.contains(""+i)){636 relatedCustomization.add(""+i);637 candidateReferences.add(""+i);638 candidates.add(copy);639 } else640 throw new IllegalArgumentException("Error: there should not exist same key with the name "+p.fieldKey+"in a combinedKeyValuePairs");641 }642 }643 });644 }645 });646 if (!candidates.isEmpty()){647 namedTypedValue.setCandidateReferences(candidateReferences);648 namedTypedValue.setCandidates(candidates);649 return;650 }651 // check for keyValues652 List<CustomizedRequestValueDto> ikey = customizationDtos.values().stream().filter(s-> s.keyValues!= null && s.keyValues.key.equals(namedTypedValue.getName())653 //&& (s.specificRequestTypeName== null || s.specificRequestTypeName.equals(namedTypedValue.getType().getFullTypeName()))654 ).collect(Collectors.toList());655 if (ikey.size() == 1){656 setCandidatesForNamedValue(namedTypedValue, ikey.get(0));657 } else if (ikey.size() > 1){658 throw new IllegalStateException("Error: more than one Dto for independent key with "+getKeyForCustomizedRequestValueDto(ikey.get(0)));659 }660 }661 private static void setCandidatesForNamedValue(NamedTypedValue namedTypedValue, CustomizedRequestValueDto customizedRequestValueDto){662 boolean handled = true;663 List<NamedTypedValue> candidates = new ArrayList<>();664 if (namedTypedValue instanceof PrimitiveOrWrapperParam || namedTypedValue instanceof StringParam || namedTypedValue instanceof ByteBufferParam){665 for (String v: customizedRequestValueDto.keyValues.values){666 NamedTypedValue copy= namedTypedValue.copyStructureWithProperties();667 handled = handled && setNamedValueBasedOnCandidates(copy, v);668 candidates.add(copy);669 }670 }else {671 SimpleLogger.uniqueWarn("Error: Do not support configuring pre-defined values for the type "+namedTypedValue.getType().getFullTypeName());672 return;673 }674 if (handled){675 namedTypedValue.setCandidates(candidates);676 }677 }678 private static boolean setNamedValueBasedOnCandidates(NamedTypedValue copy, String value){679 try {680 if (copy instanceof PrimitiveOrWrapperParam){681 ((PrimitiveOrWrapperParam) copy).setValueBasedOnStringValue(value);682 }else if (copy instanceof StringParam)683 copy.setValue(value);684 else if (copy instanceof ByteBufferParam)685 copy.setValue(value.getBytes());686 }catch (RuntimeException exception){687 SimpleLogger.uniqueWarn("Error: fail to generate candidates with string value "+value+" for "+copy.getName() +" with type "+copy.getType().getFullTypeName());688 return false;689 }690 return true;691 }692 private static void handleConstraint(NamedTypedValue namedTypedValue, Annotation annotation, List<CustomizedNotNullAnnotationForRPCDto> notNullAnnotations){693 if (annotation.annotationType().getName().startsWith("javax.validation.constraints")){694 JavaXConstraintHandler.handleParam(namedTypedValue, annotation);695 } else if (notNullAnnotations != null && !notNullAnnotations.isEmpty()){696 boolean isRequired = notNullAnnotations.stream().anyMatch(a-> isRequired(annotation, a));697 namedTypedValue.setNullable(!isRequired);698 }699 // remove the log for the moment, might need it later700// else {701// SimpleLogger.info("annotation with "+ annotation.annotationType().getName()+" is not handled");702// }703 }704 private static boolean isRequired(Annotation annotation, CustomizedNotNullAnnotationForRPCDto notNullAnnotations){705 if (annotation.annotationType().getName().equals(notNullAnnotations.annotationType)){706 if (notNullAnnotations.annotationMethod != null && notNullAnnotations.equalsTo !=null){707 try {708 return annotation.annotationType().getDeclaredMethod(notNullAnnotations.annotationMethod).invoke(annotation).equals(notNullAnnotations.equalsTo);709 } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {710 SimpleLogger.uniqueWarn("Error: fail to invoke the specified method in the annotation with the error msg:"+e.getMessage());711 return false;712 }713 }714 return true;715 }716 return false;717 }718 private static Class<?> getTemplateClass(Type type, Map<TypeVariable, Type> genericTypeMap){719 Type actualType = type;720 if (type instanceof TypeVariable)721 actualType = getActualType(genericTypeMap, (TypeVariable) type);722 if (actualType instanceof ParameterizedType){723 return (Class<?>) ((ParameterizedType)actualType).getRawType();724 }else if (actualType instanceof Class)725 return (Class<?>) actualType;726 throw new RuntimeException("unhanded type:"+ type);727 }728 /**729 * there might exist some additional info generated by eg instrumentation730 * then we need to skip reflection on such info with the specified name731 * @param name is a name of object to check732 * @return whether to skip the object733 */734 private static boolean doSkipReflection(String name){735 return name.equals("$jacocoData");736 }737 private static boolean isMetaMap(Field field){738 boolean result = field.getName().equals("metaDataMap")739 && Map.class.isAssignableFrom(field.getType());740 if (!result) return result;741 Type genericType = field.getGenericType();742 Type valueType = ((ParameterizedType) genericType).getActualTypeArguments()[1];743 return valueType.getTypeName().equals("org.apache.thrift.meta_data.FieldMetaData");744 }745 private final static String NATIVE_THRIFT_DTO_INTERFACE = "org.apache.thrift.TBase";746 private final static String NATIVE_THRIFT_FIELD_SCHEMA = "metaDataMap";747 private static boolean isNativeThriftDto(Class<?> clazz){748 return clazz.getInterfaces().length > 0 && Arrays.stream(clazz.getInterfaces()).anyMatch(i-> i.getName().equals(NATIVE_THRIFT_DTO_INTERFACE));749 }750 private static void getFieldForNativeThriftDto(Class<?> clazz, List<Field> fields){751 try {752 Field metaMap_field = clazz.getDeclaredField(NATIVE_THRIFT_FIELD_SCHEMA);753 if (isMetaMap(metaMap_field)){754 Object metaMap = metaMap_field.get(null);755 if (metaMap instanceof Map){756 for (Object f : ((Map)metaMap).values()){...

Full Screen

Full Screen

getActualType

Using AI Code Generation

copy

Full Screen

1import org.evomaster.client.java.controller.problem.rpc.RPCEndpointsBuilder;2import org.evomaster.client.java.controller.problem.rpc.RPCIndividual;3import org.evomaster.client.java.controller.problem.rpc.RPCProblem;4import org.evomaster.client.java.controller.problem.rpc.RPCResult;5import org.evomaster.client.java.controller.problem.rpc.RPCResultBuilder;6import org.evomaster.client.java.controller.problem.rpc.RPCTarget;7import org.evomaster.client.java.controller.problem.rpc.RPCType;8import org.evomaster.client.java.controller.problem.rpc.RPCTypeBuilder;9import org.evomaster.client.java.controller.problem.rpc.RPCTypeData;10import org.evomaster.client.java.controller.problem.rpc.RPCTypeDataBuilder;11import org.evomaster.client.java.controller.problem.rpc.RPCTypes;12import org.evomaster.client.java.controller.problem.rpc.RPCTypesBuilder;13import org.evomaster.client.java.controller.problem.rpc.RPCVariable;14import org.evomaster.client.java.controller.problem.rpc.RPCVariableBuilder;15import org.evomaster.client.java.controller.problem.rpc.RPCVariableData;16import org.evomaster.client.java.controller.problem.rpc.RPCVariableDataBuilder;17import org.evomaster.client.java.controller.problem.rpc.RPCVariableType;18import org.evomaster.client.java.controller.problem.rpc.RPCVariableTypeBuilder;19import java.util.ArrayList;20import java.util.Arrays;21import java.util.List;22public class RPCProblemExample {23 public static void main(String[] args) {24 RPCProblem problem = new RPCProblem();25 RPCTypes types = new RPCTypesBuilder()26 .addTypes(Arrays.asList(27 new RPCTypeBuilder()28 .withName("Person")29 .withProperties(Arrays.asList(30 new RPCVariableBuilder()31 .withName("name")32 .withType(RPCVariableType.STRING)33 .build(),34 new RPCVariableBuilder()35 .withName("age")36 .withType(RPCVariableType.INTEGER)37 .build()38 .build()39 .build();40 problem.setTypes(types);41 problem.setTargets(Arrays.asList(42 new RPCTargetBuilder()43 .withName("addPerson")44 .withMethod("POST")45 .withPath("/rpc")46 .withReturnType(RPCTypeBuilder.emptyType())47 .withParameters(Arrays.asList(48 new RPCVariableBuilder()

Full Screen

Full Screen

getActualType

Using AI Code Generation

copy

Full Screen

1package org.evomaster.client.java.controller.problem.rpc;2import org.evomaster.client.java.controller.problem.ProblemInfo;3import org.evomaster.client.java.controller.problem.rest.RestCallResult;4import org.evomaster.client.java.controller.problem.rest.RestIndividual;5import org.evomaster.client.java.controller.problem.rest.RestResourceCalls;6import org.evomaster.client.java.controller.problem.rest.RestResourceFitness;7import org.evomaster.client.java.controller.problem.rest.param.Param;8import org.evomaster.client.java.controller.problem.rest.param.PathParam;9import org.evomaster.client.java.controller.problem.rest.param.QueryParam;10import org.evomaster.client.java.controller.problem.rest.param.RequestBodyParam;11import org.evomaster.client.java.controller.problem.rest.param.HeaderParam;12import org.evomaster.client.java.controller.problem.rest.param.CookieParam;13import org.evomaster.client.java.controller.problem.rest.param.FormParam;14import org.evomaster.client.java.controller.problem.rest.param.PartParam;15import java.lang.reflect.Method;16import java.lang.reflect.Type;17import java.util.*;18import static org.evomaster.client.java.controller.problem.rest.RestCallResult.CallStatus.*;19public class RPCEndpointsBuilder {20 private final List<Method> methods;21 private final ProblemInfo problemInfo;22 public RPCEndpointsBuilder(List<Method> methods, ProblemInfo problemInfo) {23 this.methods = methods;24 this.problemInfo = problemInfo;25 }26 public List<RestResourceCalls> build() {27 List<RestResourceCalls> resources = new ArrayList<>();28 for (Method m : methods) {29 if (m.getDeclaringClass().equals(Object.class)) {30 continue;31 }32 if (problemInfo.isIgnored(m)) {33 continue;34 }35 String path = problemInfo.getRpcPath(m);36 if (path == null) {37 throw new IllegalArgumentException("Missing @Rpc annotation for method " + m.getName());38 }39 RestResourceCalls resource = new RestResourceCalls(path);40 resource.setHttpMethod(problemInfo.getRpcHttpMethod(m));41 resource.setBody(problemInfo.getRpcBody(m));42 resource.setHeaders(problemInfo.getRpcHeaders(m));43 resource.setCookies(problemInfo.getRpcCookies(m));44 resource.setParts(problemInfo.getRpcParts(m));

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful