All test methods in a package/solution in MSTest - mstest

I would like to get list of all Test Methods in unit test project/solution. I am using MSTest framework. I would like to get list of all test methods so that I can write some logic to implement logging of all available tests Vs what is executed and which one is being executed etc.,
I am a 1 year old novice in this field. So please provide the detailed explanation or code.

I found a post on how to do this in Nunit and was able to figure out doing it in MSTest.
var tests = new List ();
var testTypes = from t in assembly.GetTypes()
orderby t.Name
select t;
foreach (var type in testTypes)
{
var testMethods = from m in type.GetMethods()
let attributes = m.GetCustomAttributes(typeof(TestMethodAttribute), true)
where attributes != null && attributes.Length > 0
orderby m.Name
select m;
foreach (var method in testMethods)
{
tests.Add(method.Name);
}
}

Related

How do I know if my linq will return a useable object or a null

I am working on a web service. I am using linq to query a database. Seemingly simple, but I've run into an issue. Here is my code for reference:
List<Comment> res = new List<Comment>();
using (ApplicationHistoryEntities ahe = new ApplicationHistoryEntities())
{
res = (from columns in ahe.Comments
where columns.NetforumId == actionuniqueid
select columns).ToList();
}
If I have no entries in the database, will my .ToList() throw an error? I could deploy it, and just try it out but I want to know more about the mechanism that my linq is using. If ahe.Comments database has no rows... what will the (from...) section return?
I could just add a null reference check, use dynamics etc but I want to really understand it.
I found this Q: how to know if my linq query returns null but it seems like all of the answers are in conflict on how it really should be done...
example answers:
Either you can convert it to list and then check the count
Best approach is to check there is null(no items) in list use Any() instead of count()
LINQ queries should never return null and you should not get an exception if the result is empty. You probably have an error in your code.
You can realise the result as a list then check the items.
You can see why I question how it works.
Edit:
Final code looks like this:
List<Comment> res;
using (ApplicationHistoryEntities ahe = new ApplicationHistoryEntities())
{
res = ahe.Comments?.Where(rowItem => rowItem.NetforumId == actionuniqueid).ToList() ??
new List<Comment>().ToList();
}
Look at this example:
List<string> test = new List<string>();
var test1 = test.Where(x => x == "a").ToList();
If test exists but is empty the query returns an empty list. If test is null the query throws an error. So you can adapt the query as follows
List<string> test = new List<string>();
test = null;
var test1 = test?.Where(x => x == "a") ?? new List<string>().ToList();
The query is now 'safe'. Both of the above examples return an empty list i.e. test1.Count() will return zero but will be usable.
You can also look at the definitions of Where and ToList

LINQ to Entities does not recognize the method 'System.Collections.Generic.List`1[System.Int32]

I have the following error:
LINQ to Entities does not recognize the method
'System.Collections.Generic.List`1 [System.Int32] get_st_past_enrollment_success()'
method, and this method cannot be translated into a store expression.
This is caused by the following linq
IEnumerable<subject> _subjects = (from subject in context.subjects
where
subject.enrollments.Count() < subject.sj_max_enrollment
&& subject.sj_availability == true
&& !this.get_st_past_enrollment_success().Contains(subject.sj_subject_id)
select subject);
get_st_past_enrollment_success() returns a List:
public List<int> get_st_past_enrollment_success()
{
return this.enrollments.Where(e => e.em_enrolled == false && e.em_result >= 50).Select(e => e.em_subject_id).ToList();
}
What am i doing wrong here?
Your query itself contains the method call - and Entity Framework doesn't know what to do with that. Try extracting the list fetch to before the query:
var enrollments = get_st_past_enrollment_success();
var _subjects = from subject in context.subjects
where subject.enrollments.Count() < subject.sj_max_enrollment
&& subject.sj_availability
&& !enrollments.Contains(subject.sj_subject_id)
select subject;
Also note that get_st_past_enrollment_success violates .NET naming conventions - that won't affect whether the code works, but it'll look odd to other developers who are used to the normal conventions.

LINQ to Entities does not recognize the method 'System.String Format(System.String, System.Object, System.Object)'

I have this linq query:
private void GetReceivedInvoiceTasks(User user, List<Task> tasks)
{
var areaIds = user.Areas.Select(x => x.AreaId).ToArray();
var taskList = from i in _db.Invoices
join a in _db.Areas on i.AreaId equals a.AreaId
where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
select new Task {
LinkText = string.Format(Invoice {0} has been received from {1}, i.InvoiceNumber, i.Organisation.Name),
Link = Views.Edit
};
}
It has issues though. I'm trying to create tasks. For each new task when I set the link text to a constant string like "Hello" it is fine. However above I'm trying to build the property linktext using properties of the invoice.
I get this error:
base {System.SystemException} = {"LINQ to Entities does not recognize the method 'System.String Format(System.String, System.Object, System.Object)' method, and this method cannot be translated into a store expression."}
Anyone know why? Anyone know an alternative way of doing this to make it work?
Entity Framework is trying to execute your projection on the SQL side, where there is no equivalent to string.Format. Use AsEnumerable() to force evaluation of that part with Linq to Objects.
Based on the previous answer I have given you I would restructure your query like this:
int statusReceived = (int)InvoiceStatuses.Received;
var areaIds = user.Areas.Select(x=> x.AreaId).ToArray();
var taskList = (from i in _db.Invoices
where i.Status == statusReceived && areaIds.Contains(i.AreaId)
select i)
.AsEnumerable()
.Select( x => new Task()
{
LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.Organisation.Name),
Link = Views.Edit
});
Also I see you use related entities in the query (Organisation.Name) make sure you add the proper Include to your query, or specifically materialize those properties for later use, i.e.:
var taskList = (from i in _db.Invoices
where i.Status == statusReceived && areaIds.Contains(i.AreaId)
select new { i.InvoiceNumber, OrganisationName = i.Organisation.Name})
.AsEnumerable()
.Select( x => new Task()
{
LinkText = string.Format("Invoice {0} has been received from {1}", x.InvoiceNumber, x.OrganisationName),
Link = Views.Edit
});
IQueryable derives from IEnumerable, the main resemblance is that when you make your query it is posted to the database engine in it's language, the thin moment is where you tell C# to handle the data on the server(not client side) or to tell SQL to handle data.
So basically when you say IEnumerable.ToString(), C# gets the data collection and calls ToString() on the object.
But when you say IQueryable.ToString() C# tells SQL to call ToString() on the object but there is no such method in SQL.
The drawback is that when you handle data in C# the whole collection that you are looking through must be built up in memory before C# applies the filters.
Most efficient way to do it is to make the query as IQueryable with all the filters that you can apply.
And then build it up in memory and make the data formatting in C#.
IQueryable<Customer> dataQuery = Customers.Where(c => c.ID < 100 && c.ZIP == 12345 && c.Name == "John Doe");
var inMemCollection = dataQuery.AsEnumerable().Select(c => new
{
c.ID
c.Name,
c.ZIP,
c.DateRegisterred.ToString("dd,MMM,yyyy")
});
While SQL does not know what to do with a string.Format it can perform string concatenation.
If you run the following code then you should get the data you are after.
var taskList = from i in _db.Invoices
join a in _db.Areas on i.AreaId equals a.AreaId
where i.Status == InvoiceStatuses.Received && areaIds.Contains(a.AreaId)
select new Task {
LinkText = "Invoice " + i.InvoiceNumber + "has been received from " + i.Organisation.Name),
Link = Views.Edit
};
Once you actually perform the query this should be marginally faster than using AsEnumerable (at least that's what I found in my own code after having the same original error as you). If you are doing something more complex with C# then you will still need to use AsEnumerable though.

How to get the Entity-SQL command text by LINQ query?

It's an exercise of EF code-first. There's a simple method. I want to get the Entity SQL command text generated by object services.
(MyDbContext is derived form DbContext. Person is a POCO class.)
using (MyDbContext context = new MyDbContext())
{
var query = context.Set<Person>().FirstOrDefault(p => p.Age == 1);
Console.WriteLine(query.Name);
var objquery = query as ObjectQuery;
if (objquery != null)
Console.WriteLine(objquery.CommandText);
}
I used to get native SQL command text by ObjectQuery.TraceString in LINQ to Entity. Now, what I need is Entity-SQL statement, NOT native SQL statement.
But, I can't cast the query from IQueryable<Person> to ObjectQuery or ObjectQuery<Person>.
I tried to get members of DbQuery by reflection. It seems that DbQuery hasn't any property about command text or trace string.
Thanks
My suggestion for what you want is using Dynamic Linq. The library (part of the Linq Samples) includes many IQueryable extensions that return Linq.DataQuery objects. Once you consume the DataQuery you'll have the expected object.
var testQuery =
db.Cases.
Where("KeyID > 1").
Take(1);
foreach (var r in testQuery)
{
Console.WriteLine(r);
}
Then, you can check against your query as such.
testQuery.Expression
testQuery.Provider
These will give you:
{Table(Case).Where( => (.Keyid > 1)).Take(1)}
System.Linq.Expressions.Expression {System.Linq.Expressions.MethodCallExpression}
-and-
{SELECT TOP (1) [t0].[Keyid], [t0].[FileNo], [t0].[MatterType], [t0].[LoanNo], [t0].[Investor], [t0].[LoanType], [t0].[Client], [t0].[ClientFileNo], [t0].[ClientStatus], [t0].[Mortgagor], [t0].[County], [t0].[PropertyStreet1], [t0].[PropertyStreet2], [t0].[PropertyCity], [t0].[PropertyState], [t0].[PropertyZipcode], [t0].[Status], [t0].[BoxNo], [t0].[InsurerLoanno], [t0].[InvestorLoanno], [t0].[insurer_name_id], [t0].[OldSystemKey], [t0].[FinalBilling], [t0].[HoldBilling], [t0].[LastModified], [t0].[PiggyLoanNo], [t0].[CurrComentID], [t0].[LockEFILE], [t0].[MSJAmount], [t0].[Created], [t0].[Locked], [t0].[FinalBillingDate], [t0].[HoldBillingDate], [t0].[CreatedBy], [t0].[Stage], [t0].[PriorStage], [t0].[DefendantUpdated], [t0].[VestingCode], [t0].[FileSource], [t0].[SubVestingCode], [t0].[AttorneyAssigment], [t0].[VoluntarySurrender], [t0].[FNMARisk], [t0].[Source], [t0].[REO_ID], [t0].[WTI_ID], [t0].[CaseDismissed], [t0].[REO_CompanyID], [t0].[SubMattertype], [t0].[VendorCode], [t0].[SubType]
FROM [dbo].[Cases] AS [t0]
WHERE [t0].[Keyid] > #p0}
System.Linq.IQueryProvider {System.Data.Linq.DataQuery<CMSDEVMapping.Case>}
You can also verify your type in the loop:
r.GetType() {Name = "Case" FullName = "CMSDEVMapping.Case"} System.Type {System.RuntimeType}

How to take the result of a Linq CompiledQuery

Linq and compiled queries
This is my code:
I need to associated the value of a properties a.Value to a Literal.Text property.
Any idea how to do it?
Thanks for your valuable help!
using (var context = new CmsConnectionStringEntityDataModel())
{
context.CmsOptions.MergeOption = MergeOption.NoTracking;
var query = CompiledQuery.Compile<CmsConnectionStringEntityDataModel, IQueryable<CmsOption>>
(ctx => from a in ctx.CmsOptions where a.OptionId == 7 select a);
uxHeaderIncluder.Text = // What I do here?;
}
Have you looked at these examples:
http://www.blog.ingenuitynow.net/15+Minutes+On+LINQ+Compiled+Queries.aspx
http://msdn.microsoft.com/en-us/library/bb896297.aspx
The core of the approach is to spesify the input type(s) in the Compile method call.
Your compile call should be something like this:
CompiledQuery.Compile<CmsConnectionStringEntityDataModel,string,string, IQueryable<CmsOption>>
((ctx,str1,str2)=>from a in ctx.CmsOptions where a.OptionId == 7 && /* use str1 and str2 params here */ select a);

Resources