The article structure
- Jmeter loads the results
-
- Generate a Jmeter test plan
- Extract API from Controller
- Generate jmeter
- Source code can be contacted by the author
A test engineer who does not know how to use Jmeter is not a good programmer. When handing over your own API to front-end development, do you have any confidence? What is a JMeter? Apache JMeter is a pure Java written load functional testing and performance testing open source tools. Compared to Loadrunner, JMeter is small, lightweight and free, and has gradually become a mainstream performance testing tool that every tester must master.
Jmeter loads the results
First of all, the quick Jmeter test routine doesn’t actually have the right data. It’s just randomly generated data, but the structure is correct. Therefore, you need to adjust the test data and test sequence, and then you can play happy, remember to save after playing, next time if there is API change, you can continue to verify the impact of the change, front-end problems can also be quickly feedback.
Generate a Jmeter test plan
Open a Jmeter test plan and find XML, as shown below.
Xmlwriter to support writing XML
/// <summary>
///Writes < 'elementName' name='name' elementType='elementType'>
/// </summary>
internal static void WriteStartElement(XmlWriter xmlWriter, string elementName, string name, string elementType)
{
xmlWriter.WriteStartElement(elementName);
xmlWriter.WriteAttributeString("name", name);
xmlWriter.WriteAttributeString("elementType", elementType);
}
/// <summary>
///Writes < 'elementName' name='name'>
/// </summary>
internal static void WriteStartElement(XmlWriter xmlWriter, string elementName, string name)
{
xmlWriter.WriteStartElement(elementName);
xmlWriter.WriteAttributeString("name", name);
}
/// <summary>
///Writes < 'elementName' name='name'> < /'elementName'>
/// </summary>
internal static void WriteStartAndEndElement(XmlWriter xmlWriter, string elementName, string name)
{
xmlWriter.WriteStartElement(elementName);
xmlWriter.WriteAttributeString("name", name);
xmlWriter.WriteEndElement();
}
/// <summary>
///Writes < 'elementName'> 'value'< /'elementName'>
/// </summary>
internal static void WriteSimpleElement(XmlWriter xmlWriter, string elementName, string elementValue)
{
xmlWriter.WriteStartElement(elementName);
xmlWriter.WriteString(elementValue);
xmlWriter.WriteEndElement();
}
/// <summary>
///Writes < 'elementName' name='valueOfPropName'> 'elementValue'< /'elementName'>
/// </summary>
internal static void WriteElementWithTextChildren(XmlWriter xmlWriter, string elementName, string valueOfPropName,
string elementValue)
{
xmlWriter.WriteStartElement(elementName);
xmlWriter.WriteAttributeString("name", valueOfPropName);
xmlWriter.WriteString(elementValue);
xmlWriter.WriteEndElement();
}
Copy the code
Extract API from Controller
Of course, I do not write all of them, using ObjectGenerator to change. This class should be Microsoft official or Swagger, directly used to modify. The auxiliary classes are as follows:
public class ApiHelper
{
public static List<TestApi> GetAllControllers(string assembly)
{
List<TestApi> apis = new List<TestApi>();
var asm = Assembly.Load(assembly);
var ctls = asm.GetTypes().Where(x => x.BaseType == typeof(Controller) || x.IsSubclassOf(typeof(Controller)));
var list = ctls.ToList();
foreach (var ctl in ctls)
{
var methods = GetAllMetods(ctl);
var r = GetRoute(ctl);
foreach (var m in methods)
{
var api = new TestApi();
var isPost = IsPost(m);
var desc = GetDesc(m);
api.Title = desc;
api.post = isPost;
if (string.IsNullOrEmpty(desc)) continue;
var route = GetRoute(m);
if (string.IsNullOrEmpty(r))
{
api.uri = $"api/{ctl.Name.Replace("Controller"."")}/{m.Name}";
}
else
{
if (string.IsNullOrEmpty(route))
{
api.uri = r.Replace("[controller]", ctl.Name.Replace("Controller"."")).Replace("[action]", m.Name);
}
else
{
if (r.Contains("[action]"))
api.uri = r.Replace("[controller]", ctl.Name.Replace("Controller"."")).Replace("[action]", route);
else
api.uri = r.Replace("[controller]", ctl.Name.Replace("Controller"."")) + $" /{route}"; }}var pas = m.GetParameters();
if (isPost)
{
ObjectGenerator og = new ObjectGenerator();
varobj = og.GenerateObject(pas.FirstOrDefault()? .ParameterType ??typeof(object));
//var json = JsonConvert.SerializeObject(obj, new JsonSerializerSettings
/ / {
// Formatting = Formatting.Indented,
/ /});
api.inParam = obj;
}
else
{
foreach (var p in pas)
{
if (string.IsNullOrEmpty(api.inParam))
api.inParam = $"{p.Name}=";
else
api.inParam += $" &{p.Name}="; } } apis.Add(api); }}return apis;
}
public static List<MethodInfo> GetAllMetods(Type type)
{
return type.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.DeclaredOnly |
BindingFlags.Instance).ToList();
}
public static bool IsPost(MethodInfo m)
{
var cas = m.GetCustomAttributes(false);
var post = (HttpPostAttribute)(cas.ToList().FirstOrDefault(x => x.GetType() == typeof(HttpPostAttribute)));
returnpost ! =null;
}
public static string GetRoute(MethodInfo m)
{
var cas = m.GetCustomAttributes(true);
var route = (RouteAttribute)(cas.ToList().FirstOrDefault(x => x.GetType() == typeof(RouteAttribute)));
returnroute? .Template; }public static string GetDesc(MethodInfo m)
{
var cas = m.GetCustomAttributes(true);
var route = (DisplayAttribute)(cas.ToList().FirstOrDefault(x => x.GetType() == typeof(DisplayAttribute)));
returnroute? .Name; }public static string GetRoute(Type m)
{
var cas = m.GetCustomAttributes(true);
var route = (RouteAttribute)(cas.ToList().FirstOrDefault(x => x.GetType() == typeof(RouteAttribute)));
return route?.Template;
}
}
public class TestApi
{
/// <summary>
///Relative paths
/// </summary>
public string uri { get; set; }
public string Title { get; set; }
public bool post { get; set; }
public dynamic inParam { get; set; }
public string test { get; set; }
public bool testResult { get; set; }
public string rtnError { get; set; }}Copy the code
Generate jmeter
var apis = ApiHelper.GetAllControllers("SCM.AMS.AmsWxApp.APIs");
var jmeter = new JMeterGenerator();
var dir = Assembly.GetExecutingAssembly().Location;
FileInfo fi = new FileInfo(dir);
jmeter.Save(apis, fi.DirectoryName, "abc");
Copy the code
Source code can be contacted by the author
Source can contact me! This can be written as needed, because there is no good abstraction of a tool, so it is not embarrassing.