I'm trying to compare a string but the document no in my string is always different and I don't want my unit test to fail. I really just want to check if the document posted.
In my example, it is the document no that may not match.
Assert.AreEqual("1 Document(s) Posted. Document QA00752 has been created.",
message, "Post Confirmation Message does not match expected");
Any suggestions? I could find out what the document no is supposed to be by checking the data in the database and write it out to a variable but I don't know how to put it in my statement above.
string doc = "some code goes here"
Perhaps
Assert.AreEqual("1 Document(s) Posted. Document " + doc + " has been created.",
message, "Post Confirmation Message does not match expected");
I think that trying to parse a message to remove specific identifiers is problematic. If this is just a one-time thing, and you won't be checking various strings as a habit in your testing, then a simple .Contains or a regex could work.
But, if you're doing this task all over the place, then perhaps some abstraction is in order. Have you considered making your log messages into an object instead of a simple string?
public sealed class Notification {
public string Message { get; set; }
public string Identifier { get; set; }
public int? Count { get; set; }
}
Then when you're working with these notifications such as in a unit test, you can compare the Message property to see it's identical, but ignore the Identifier and Count.
Here's another way you could do it:
public sealed class InterpolatedString {
public InterpolatedString(string stringWithPlaceholders, params string[] values) {
StringWithPlaceholders = stringWithPlaceholders;
Values = values;
}
public string StringWithPlaceholders { get; }
public string[] Values { get; }
public override string ToString() => string.Format(StringWithPlaceholders, Values);
}
You'd create that like this:
return new InterpolatedString(
"{0} Document(s) Posted. Document {1} has been created.",
$"{count:#,##0}",
documentCode
);
Then when testing or grouping, you have access to the non-interpolated string.
var actual = DoTest();
Assert.AreEqual(
"{0} Document(s) Posted. Document {1} has been created.",
actual.StringWithPlaceholders
);
And finally, any time you want the actual string, you can just do ToString() or let it get implicitly run when a compiler-supported implicit conversion to string occurs.
There is the problem of having to repeat a string and the risk of breaking a unit test if you change the string in the code. However, if you put your strings into a resource file, then you don't even need to repeat them in two places—you can just use the resource file to spit them out. Another option is to keep strings in public static members instead of embedded deep in the code.
If you need pattern matching, then a regular expression (as mentioned by SLaks) is the cleanest way to go:
Assert.IsTrue(
Regex.IsMatch(message, #"1 Document\(s\) Posted. Document QA\d+ has been created."),
"Post Confirmation Message does not match expected");
Just assert that the message Contains("has been created"), unless there are conditions where that won't pass.
Related
I just discovered this nice tool XmlUnit that allows me to evaluate 2 different XML documents and display the eventual discrepencies.
string control = "<a><b attr=\"abc\"></b></a>";
string test = "<a><b attr=\"xyz\"></b></a>";
var myDiff = DiffBuilder.Compare(Input.FromString(control))
.WithTest(Input.FromString(test))
.Build();
Assert.IsFalse(myDiff.HasDifferences(), myDiff.ToString());
However, I have found that the myDiff.ToString() only displays the first difference encountered.
Is there a way to display them all ?
I just found the solution
Assert.IsFalse(myDiff.HasDifferences(), string.Join(Environment.NewLine, myDiff.Differences));
I assume that you are using the xmlunit.net library (You didn't say the name of the tool that you found but your example seems to match).
You can search their GitHub repo and find the DiffBuilder class file. If you look at the Build method you will see it returns a Diff object. If you go to the Diff class file you will find that it's ToString method looks like this.
public override string ToString() {
return ToString(formatter);
}
Which doesn't tell you a lot but if you go to the other ToString overload you find this.
public string ToString(IComparisonFormatter formatter) {
if (!HasDifferences()) {
return "[identical]";
}
return differences.First().Comparison.ToString(formatter);
}
Now we are getting somewhere. We now know that Diff stores its list of differences in a private differences field and why ToString() only returns one difference (The .First() call). If you look through that class you will find that there's a public property called Differences which exposes that field as an IEnumerable. So the way to get all differences is to loop through that property and collect all of them like so.
string control = "<a><b attr=\"abc\" attr2=\"123\"></b></a>";
string test = "<a><b attr=\"xyz\" attr2=\"987\"></b></a>";
var myDiff = DiffBuilder.Compare(Input.FromString(control))
.WithTest(Input.FromString(test))
.Build();
var sb = new StringBuilder();
foreach(var dif in myDiff.Differences)
{
sb.AppendLine(dif.Comparison.ToString());
}
Assert.IsFalse(myDiff.HasDifferences(), sb.ToString());
Note that I got the syntax for formatting the difference from the Diff class's ToString code. Also notice that I added a second attribute to your examples to demonstrate that this really is showing all the differences.
I am a little rusty on my C# and I am trying to figure out a simple script to use in SSIS that will comb through a text file and extract values based on a specific set of patterns and a specific sequence of said patterns.
I need to specify the individual rows of values from this text input to pass to a text file as output. So contract no, bank num, etc are heads and each row is a wrapped value within the file. I just need to be able to comb through and ID rows for output and was thinking that a regular expression could do the trick but I am unsure how to put something like that together. Is it possible to have it ID each row by looking for value patterns in a particular sequence?
I.E.
Pattern1 = [0-9] {9} for contract num
Pattern2 = [a-z][0-9] {6} for bank num
But look for instances where Pattern1 is before Pattern2?
I hope that makes sense.
Any and all help is greatly appreciated.
Thanks.
Sample Text
The file you're working with appears to be fixed width; whoever wrote the program that generates this file, he was communicating the meaning of each field by its position. So it is best that your program consume the information the way it was passed, by interpreting the data based on its position, not its ability to match a particular regular expression. That being said, regular expressions would be a great way to validate the data after it is parsed.
To work with this kind of data, I would probably build a class that represents a single record, and give it methods for parsing and validating. Here is something I came up with pretty quickly:
public class DetailRecord
{
private readonly string _originalText;
static private Dictionary<string, Func<string,string>> _map = new Dictionary<string, Func<string,string>>
{
{ "ContractNo", s => s.Substring( 1 ,10 ) },
{ "BankNum", s => s.Substring( 15 , 8 ) },
{ "ShortName", s => s.Substring( 35 ,10 ).Trim() }
};
public DetailRecord(string originalText)
{
_originalText = originalText;
}
public string this[string key]
{
get
{
return _map[key](_originalText);
}
}
public string BankNum
{
get { return this["BankNum"]; }
}
public string ContractNo
{
get { return this["ContractNo"]; }
}
public string ShortName
{
get { return this["ShortName"]; }
}
public bool IsValid
{
get
{
int dummy;
if (!int.TryParse(this.ContractNo, out dummy)) return false;
if (!Regex.IsMatch(this.BankNum, #"[A-Z]\d\d\s\s\d\d\d")) return false;
return true;
}
}
}
You'll notice this class keeps a static dictionary (the _map) which contains a list of functions for parsing each field.
Also notice there is an IsValid property which uses a regular expression to validate the bank number. The contract number appears to be straight numeric, and it validates that too.
Test program:
public class Program
{
public static void Main()
{
var input = " 0759651386 X08 606 0209784104 BURTON 3334.24";
var line = new DetailRecord(input);
if (line.IsValid)
{
Console.WriteLine("Contract number: '{0}'", line.ContractNo);
Console.WriteLine("Bank number: '{0}'", line.BankNum);
Console.WriteLine("Short name: '{0}'", line.ShortName);
}
}
}
Output:
Contract number: '0759651386'
Bank number: 'X08 606'
Short name: 'BURTON'
See my code on DotNetFiddle
I want to include some special characters in a string variable name in C#.
Example:
string foo-bar = String.Empty;
As far as my understand I can't declare a variable as I mentioned in the above example.
Is there any way around to declare a variable name with "-" included?
From MSDN:
You can't just choose any sequence of characters as a variable name. This isn't as worrying as it might sound, however, because you're still left with a very flexible naming
system.
The basic variable naming rules are as follows:
The first character of a variable name must be either a letter, an underscore character (_), or the at symbol (#).
Subsequent characters may be letters, underscore characters, or numbers.
No, this is not possible to do in C#.
If you really, really, really want to so this, you could use a Dictionary<string, string>:
Dictionary<string, string> someVars = new Dictionary<string, string>()
{
{"foo-bar", String.Empty},
{"bar-foo", "bazinga"}
}
Using them would look like this:
string newstring = someVars["foo-bar"] + "Hello World!";
Instead of just using the variable name, you would look up the string in your dictionary. Note that this is very inefficient and just intended as a joke, so please do no really use this ;)
If you are trying to deserialize object, you can use JsonProperty to acieve this.
Example:
public class SubscriptionListJsonData
{
[JsonProperty(PropertyName = "subscriptions")]
public string SubscriptionData { get; set; }
[JsonProperty(PropertyName = "#nextLink")]
public string nextLink { get; set; }
}
Follow this link for partially reading Json.
You can't do that in c# and most of other programming languages .. I also advice you to follow the C# naming conventions as it help you read your code in a way that -at least for me- always felt comfortable .
I want to search in my data. I'm using regular expression with IsMatch() function.
I have a class:
public class MyClass
{
public string Name { get; set; }
public string Address { get; set; }
}
I want to search in my data by Name Or Address, and Name or Address Like input
With input FuzzySearch is: a%b or a%b%c or japanese characters (ex:区%水).
In main function I have a list: List<MyClass> data and using regular expression with IsMatch() function as below:
Regex regex = new Regex(FuzzySearch, RegexOptions.IgnoreCase);
var allInfoList1 = allInfoList.Where(x => regex.IsMatch(x.Name) ||
regex.IsMatch(x.Address)).ToList();
Sometime result is true, but sometime result is wrong( with case input is japanese characters)
(Is the regular expression not support unicode?)
Are there any other solutions?
Rather than implementing your own document search engine, I would suggest considering tools like Apache Lucene or Apache Solr. I do not know your specific use case, and perhaps my suggestion is an overkill, but I would give it a thought.
Hope I helped!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to add { in String Format c#
When i'm rewriting always the same thing, i'm used to write what I call a string pattern of it.
Let's say I would like to do SQL injection to extend ORM functionality...
protected static string FULLTEXTPATTERN = "EXISTS CONTAINSTABLE([{0}],*,'\"{1}\"') WHERE [key] = {0}.id;
And usually I got the table name and value that i combine in a string.format(FULLTEXTPATTERN ,...) and everything is fine.
Imagine now, I have to do that in two time. first injecting the table name, then the value I search for. So I would like to write something like:
protected static string FULLTEXTPATTERN = "EXISTS CONTAINSTABLE([{0}],*,'\"{{0}}/*Something that returns {0} after string.format*/\"') WHERE [key] = {0}.id;
...
var PartialPattern= string.fomat(FULLTEXTPATTERN, "TableX");
//PartialPattern = "EXISTS CONTAINSTABLE([TableX],*,'\"{0}\"') WHERE [key] = {0}.id"
...
//later in the code
...
var sqlStatement = string.format(PartialPattern,"Pitming");
//sqlStatement = "EXISTS CONTAINSTABLE([TableX],*,'\"Pitming\"') WHERE [key] = {0}.id"
Is there a way to do it ?
Logic says that you would simply put {{{0}}} in the format string to have it reduce down to {0} after the second string.Format call, but you can't - that throws a FormatException. But that's because you need yet another { and }, otherwise it really is not in the correct format :).
What you could do - set your full format to this (note the 4 { and } characters at the end):
"EXISTS CONTAINSTABLE([{0}],*,'\"{{0}}\"') WHERE [key] = {{{{0}}}}.id";
Then your final string will contain the {0} you expect.
As a proof - run this test:
[TestMethod]
public void StringFormatTest()
{
string result = string.Format(string.Format(
"{0} {{0}} {{{{0}}}}", "inner"), "middle");
Assert.AreEqual("inner middle {0}", result);
}
Is it possible to delay generating SQL to the point at which you have all the required inputs so that you can use one call to String.Format() and multiple fields?
Alternatively, you could you build the query iteratively using a StringBuilder rather than String.Format().