Here's my object:
public class Symbol
{
private readonly string _identifier;
private readonly IList<Quote> _historicalQuotes;
public Symbol(string identifier, IEnumerable<Quote> historicalQuotes = null)
{
_identifier = identifier;
_historicalQuotes = historicalQuotes;
}
}
public class Quote
{
private readonly DateTime _tradingDate;
private readonly decimal _open;
private readonly decimal _high;
private readonly decimal _low;
private readonly decimal _close;
private readonly decimal _closeAdjusted;
private readonly long _volume;
public Quote(
DateTime tradingDate,
decimal open,
decimal high,
decimal low,
decimal close,
decimal closeAdjusted,
long volume)
{
_tradingDate = tradingDate;
_open = open;
_high = high;
_low = low;
_close = close;
_closeAdjusted = closeAdjusted;
_volume = volume;
}
}
I need an instance of Symbol populated with a list of Quote.
An in my test, I want to verify that I can return all quotes which the close price is under or above a specific value. Here's my test:
[Fact]
public void PriceUnder50()
{
var msftIdentifier = "MSFT";
var quotes = new List<Quote>
{
new Quote(DateTime.Parse("01-01-2009"), 0, 0, 0, 49, 0, 0),
new Quote(DateTime.Parse("01-02-2009"), 0, 0, 0, 51, 0, 0),
new Quote(DateTime.Parse("01-03-2009"), 0, 0, 0, 50, 0, 0),
new Quote(DateTime.Parse("01-04-2009"), 0, 0, 0, 10, 0, 0)
};
_symbol = new Symbol(msftIdentifier, quotes);
var indicator = new UnderPriceIndicator(50);
var actual = indicator.Apply(_symbol);
Assert.Equal(2, actual.Count);
Assert.True(actual.Any(a => a.Date == DateTime.Parse("01-01-2009")));
Assert.True(actual.Any(a => a.Date == DateTime.Parse("01-04-2009")));
Assert.True(actual.Any(a => a.Price == 49));
Assert.True(actual.Any(a => a.Price == 10));
}
OK.
Now, I wanna do it using Autofixture, im a real beginner. I've read pretty much everything I could on internet about this tool (the author's blog, codeplex FAQ, github source code). I understand the basic features of autofixture, but now I wanna use autofixture in my real project. Here's what I tried so far.
var msftIdentifier = "MSFT";
var quotes = new List<Quote>();
var random = new Random();
fixture.AddManyTo(
quotes,
() => fixture.Build<Quote>().With(a => a.Close, random.Next(1,49)).Create());
quotes.Add(fixture.Build<Quote>().With(a => a.Close, 49).Create());
_symbol = new Symbol(msftIdentifier, quotes);
// I would just assert than 49 is in the list
Assert.True(_symbol.HistoricalQuotes.Contains(new Quote... blabla 49));
Ideally, I would prefer to directly create a fixture of Symbol, but I don't know how to customize my list of quotes. And I'm not sure that my test is generic, because, in another test, I will need to check that a specific value is above instead of under, so I'm gonna duplicate the "fixture code" and manual add a quote = 51.
So my questions are:
1 - Is it the way how I'm supposed to use autofixture?
2 - Is it possible to improve the way I use autofixture in my example ?
AutoFixture was originally build as a tool for Test-Driven Development (TDD), and TDD is all about feedback. In the spirit of GOOS, you should listen to your tests. If the tests are hard to write, you should consider your API design. AutoFixture tends to amplify that sort of feedback, and here's what it's telling me.
Make comparison easier
First, while not related to AutoFixture, the Quote class just begs to be turned into a proper Value Object, so I'll override Equals to make it easier to compare expected and actual instances:
public override bool Equals(object obj)
{
var other = obj as Quote;
if (other == null)
return base.Equals(obj);
return _tradingDate == other._tradingDate
&& _open == other._open
&& _high == other._high
&& _low == other._low
&& _close == other._close
&& _closeAdjusted == other._closeAdjusted
&& _volume == other._volume;
}
(Make sure to override GetHashCode too.)
Copy and update
The above attempt at a test seems to imply that we're lacking a way to vary a single field while keeping the rest constant. Taking a cue from functional languages, we can introduce a way to do that on the Quote class itself:
public Quote WithClose(decimal newClose)
{
return new Quote(
_tradingDate,
_open,
_high,
_low,
newClose,
_closeAdjusted,
_volume);
}
This sort of API tends to be very useful on Value Objects, to the point where I always add such methods to my Value Objects.
Let's do the same with Symbol:
public Symbol WithHistoricalQuotes(IEnumerable<Quote> newHistoricalQuotes)
{
return new Symbol(_identifier, newHistoricalQuotes);
}
This makes it much easier to ask AutoFixture to deal with all the stuff you don't care about while explicitly stating only that which you care about.
Testing with AutoFixture
The original test can now be rewritten as:
[Fact]
public void PriceUnder50()
{
var fixture = new Fixture();
var quotes = new[]
{
fixture.Create<Quote>().WithClose(49),
fixture.Create<Quote>().WithClose(51),
fixture.Create<Quote>().WithClose(50),
fixture.Create<Quote>().WithClose(10),
};
var symbol = fixture.Create<Symbol>().WithHistoricalQuotes(quotes);
var indicator = fixture.Create<UnderPriceIndicator>().WithLimit(50);
var actual = indicator.Apply(symbol);
var expected = new[] { quotes[0], quotes[3] };
Assert.Equal(expected, actual);
}
This test only states those parts of the test case that you care about, while AutoFixture takes care of all the other values that don't have any impact on the test case. This makes the test more robust, as well as more readable.
Related
I have been using TMP objects in several instances in my game, but all of a sudden it decides not to work on a certain object.
public class BeforeRoundTimer : MonoBehaviour
{
public TextMeshProUGUI timer;
private Timer oneSecondTimer;
private int time = 5;
public void StartCountdown()
{
Debug.Log("One second timer");
oneSecondTimer = new Timer(1000);
oneSecondTimer.Elapsed += UpdateTime;
oneSecondTimer.Enabled = true;
oneSecondTimer.AutoReset = true;
oneSecondTimer.Start();
}
private void UpdateTime(object source, ElapsedEventArgs e)
{
if(time == 0)
{
oneSecondTimer.Stop();
return;
}
timer.text = $"{time}";
time--;
}
}
I know the text is updating because I put debug statements (I have since removed them) and they fired when UpdateTime() is called. I also viewed the inspector when the game was playing, and the text value would update in front of my eyes. The text only changes when I make some stylistic change to it (i.e. making it bold, changing the font asset, including changing the text itself). I have looked back to my old code and it basically runs the exact same way, but it actually changes in game.
Ok so after taking a break, I decided to find another way to call my method every second. Instead of using a Timer, I decided to use Unity's InvokeRepeating() function.
public class BeforeRoundTimer : MonoBehaviour
{
public TextMeshProUGUI timer;
private int count = 0;
public void StartCountdown()
{
InvokeRepeating(nameof(UpdateTime), 0, 1f);
}
private void UpdateTime()
{
if(count == 5)
{
CancelInvoke("UpdateTime");
return;
}
Debug.Log("Update Time");
timer.text = $"{5 - count}";
count++;
}
}
One thing I noticed when trying to use the Timer in a different way is that it was only updating the text value every other second. It ran 10 times (I put a Debug.Log() in UpdateTime()) but only changed the value every other time while not actually updating the TMP. You could replace nameof(UpdateTime) with "UpdateTime", but Visual Studio recommended that I use the former so I went with that.
In short: don't use timers, use Unity's InvokeRepeating() function because it works perfectly. It is actually very similar to JavaScript's setInterval() which I found interesting.
Record is a new feature in c#9, Net 5
It's said
If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record
Creating a record in c#9 , NET 5:
public record Rectangle
{
public int Width { get; init; }
public int Height { get; init; }
}
Then instantiating it:
var rectangle = new Rectangle (20,30);
Trying to change the value:
rectange.Width=50; //compiler error
Compiler raise the error:
error CS8852: Init-only property or indexer 'Rectangle.Width' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.
That is right and insure that the record is immutable.
Using a method like to test IsImmutable type give false, because in record there is no generated readonly properties.
How to check the record in c# 9, Net 5 is immutable at runtime or even it has init property?
A record is indeed mutable at runtime. This is intentional, is it means most serializer frameworks work without updating.
It is however possible to check if a property is initonly by checking:
public static bool IsInitOnly(PropertyInfo propertyInfo)
{
return propertyInfo?.SetMethod.ReturnParameter
.GetRequiredCustomModifiers()
.Any(x => x.FullName == _isExternalInitName)
?? false;
}
private static string _isExternalInitName =
typeof(System.Runtime.CompilerServices.IsExternalInit).FullName;
I don't think that it's possible to check for immutability at runtime.
Here's some of the generated code for your record. You can see that both properties have a public setter.
public class Rectangle : IEquatable<Rectangle>
{
[CompilerGenerated]
private readonly int <Width>k__BackingField;
[CompilerGenerated]
private readonly int <Height>k__BackingField;
protected virtual Type EqualityContract
{
[CompilerGenerated]
get
{
return typeof(Rectangle);
}
}
public int Width
{
[CompilerGenerated]
get
{
return <Width>k__BackingField;
}
[CompilerGenerated]
set
{
<Width>k__BackingField = value;
}
}
public int Height
{
[CompilerGenerated]
get
{
return <Height>k__BackingField;
}
[CompilerGenerated]
set
{
<Height>k__BackingField = value;
}
}
The following code will compile and run without errors.
var rect = new Rectangle { Height = 1, Width = 2 };
typeof(Rectangle).GetProperty("Height").SetValue(rect, 5);
Console.Write(rect.Height);
//Prints 5
At runtime the init accessor is just a regular setter. It's only at compile time that a check is made to only allow init accessor to be called during object initialization.
So I don't see any way to check at runtime that Rectangle is immutable.
i seem to have a nullPointerException without any reason, could you please review piece of my code and tell me your opinion?
This is the class and the constructor that i am calling on another class in order to get a label randomly (using the shuffle, which is randomizing as well) from a linked list.
here is the
public class RandomHeuristic {
GameInterface game;
JLabel randomLabel;
public JLabel RandomHeuristic() {
randomLabel = (JLabel) game.labels.getFirst();
int counter = 0;
do {
Collections.shuffle(game.labels);
randomLabel = (JLabel) game.labels.getFirst();
counter++;
if (counter == 100) {
break;
}
/*
* Debugging
* System.out.println(randomLabel.getText());
*/
} while (randomLabel != null && game.isLegalMove(randomLabel) == false);
//Retrieves and removes the head (first element) of this list.
if(randomLabel == null){
RandomHeuristic();
}
//game.labels.remove(randomLabel);
return randomLabel;
}
}
And here is where i am calling the constructor, the playHeuristicMove() is expecting a JLabel i checked it on debugging that is working correctly, though i still get a nullPointer Exception when i call it. randomHeuristicOne is created on the same class like this: RandomHeuristic randomHeuristicOne;
playHeuristicMove(randomHeuristicOne.RandomHeuristic());
Perhaps you want to take a look at your game GameInterface object it seems it's never been instantiated
I've been following the Tasky Case Study on the MonoDroid website, but I've run into a wall whilst creating a filtering and ordering query. I was wondering if somebody could explain where I might be going wrong please? I'm probably doing something completely backwards!
I get the error:
The type arguments for method 'ICanTalk.BusinessLayer.Services.WordServices.Find(System.Func, System.Func, bool, int, int)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I have the following code in one of my repositories, hopefully what I'm trying to do is kind of clear. I haven't been able to build it yet to test to see if it works though:
public static IEnumerable<Word> Find<T,U>(Func<Word, bool> whereClause, Func<Word,U> orderBy, bool ascending, int show, int page)
{
int currentPage = page;
int resultsPerPage = show;
int skip = currentPage*show;
var result = ascending
? me.db.Find<Word>().Where(whereClause).OrderBy(orderBy).Take(resultsPerPage).Skip(skip)
: me.db.Find<Word>().Where(whereClause).OrderByDescending(orderBy).Take(resultsPerPage).Skip(skip);
return result;
}
From my services I call this method from here:
public static IList<Word> Find<T>(Func<Word, bool> whereClause, Func<Word,DateTime> orderBy, bool ascending, int show, int page)
{
return WordRepository.Find<Word, DateTime>(whereClause, orderBy, ascending, show, page).ToList();
}
What I'm trying to achieve is a call from an event handler within MonoDroid like:
var wordTest = WordServices.Find(x => x.ChildId == 3, x => x.AddedAt, true, 5, 1);
Both of your methods are generic Find<T,U> and Find<T> - but you don't seem to be using the type T anywhere in your method definition. Was T expected to be the type Word ?
U is used once in the orderBy where elsewhere you're using bool - which of those usages is a mistake?
Can you try replacing Word with T in your definitions, and bool with U (if that's what you meant to do) and then when you're calling the method actually call it with the correct type ?
var wordTest = WordServices.Find<Word>(x => x.ChildId == 3,
x => x.AddedAt,
true, 5, 1);
I had it almost right, I stripped it down to the basics and worked my way back up and came up with the following (compare to original if you're interested).
SQLiteDatabase.cs
(not in original post - I scaled the query clauses right down to a reusable method in my generic handler):
public IEnumerable<T> Find<T>(Func<T, bool> whereClause, int resultsToSkip, int resultsToShow)
where T : BusinessLayer.Contracts.IBusinessEntity, new()
{
lock (locker)
{
return Table<T>().Where(whereClause).Skip(resultsToSkip).Take(resultsToShow).ToList();
}
}
WordRepository.cs
public static IEnumerable<Word> Find<T>(Func<Word, bool> whereClause, int resultsToSkip, int resultsToShow)
where T : BusinessLayer.Contracts.IBusinessEntity, new()
{
var result = me.db.Find<Word>(whereClause, resultsToSkip, resultsToShow);
return result;
}
WordServices.cs
By this point I'm wondering why there exists a need for so many layers - will definitley look to refactor in the morning.
public static IList<Word> Find<T, U>(Func<Word, bool> whereClause, Func<Word, U> orderBy, bool ascending, int show, int page)
{
int resultsToShow = show;
int resultsToSkip = show * (page - 1);
var result = ascending ? WordRepository.Find<Word>(whereClause, resultsToSkip, resultsToShow).OrderBy(orderBy)
: WordRepository.Find<Word>(whereClause, resultsToSkip, resultsToShow).OrderByDescending(orderBy);
return result.ToList();
}
Originating Call
var wordTest1 = WordServices.Find<Word, DateTime>(x => x.ChildId == 1, x => x.AddedAt, true, 5, 1);
I know this has been an issue for a while now, and checked all previously answers I could get, but still this one doesn't work.
The object 'crew' represents crewmembers with ranks and other items. The comparison should be made by comparing 'assigned_rank', an int value, and if this value is equal in both instances, then 'is_trainer', a boolean, should make the difference.
This method worked great as long as it was running with java < 7. But since Java 7 I keep getting this one:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:714)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:451)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at dormas_flightlog.Query.getCrew(Query.java:714)
Here is the source, where some potentially dangerous parts have allready been out-commented, but it still does not work:
public class crew implements Serializable, Comparable<crew> {
private static final long serialVersionUID = 36L;
private int flightID = 0;
private int assigned_rank = 25;
private boolean is_trainer = false;
...
#Override
public int compareTo(crew him) {
int myRank = this.getAssigned_rank();
int hisRank = him.assigned_rank;
if (this == him) {
return 0;
}
if (myRank > hisRank) {
return 1;
}
if (myRank < hisRank) {
return -1;
}
if (myRank == hisRank) {
// if (is_trainer && !o.is_trainer) {
// i = 1;
// }
// if (!is_trainer && o.is_trainer) {
// i = -1;
// }
// if (is_trainer && o.is_trainer) {
// i = 0;
// }
// if (!is_trainer && !o.is_trainer) {
// i = 0;
// }
return 0;
}
return 0;
}
#Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.assigned_rank;
hash = 31 * hash + (this.is_trainer ? 1 : 0);
return hash;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
int myRank = this.getAssigned_rank();
int hisRank = 0;
if (o instanceof crew) {
crew him = (crew) o;
hisRank = him.assigned_rank;
} else {
return false;
}
if (myRank > hisRank) {
return false;
}
if (myRank < hisRank) {
return false;
}
if (myRank == hisRank) {
// if (is_trainer && !o.is_trainer) {
// i = 1;
// }
// if (!is_trainer && o.is_trainer) {
// i = -1;
// }
// if (is_trainer && o.is_trainer) {
// i = 0;
// }
// if (!is_trainer && !o.is_trainer) {
// i = 0;
// }
return true;
}
return false;
}
}
Implementing equals() was just a try to solve this problem. The given exception comes with or without equals(). I cannot see how the compareTo-method violates its contract. Any help is greatly appreciated....one day this code has to work with java 7 and I don't know how...
Thanks
see this:
From http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source
Area: API: Utilities Synopsis: Updated sort behavior for Arrays and
Collections may throw an IllegalArgumentException
Description: The sorting algorithm used by java.util.Arrays.sort and
(indirectly) by java.util.Collections.sort has been replaced. The new
sort implementation may throw an IllegalArgumentException if it detects
a Comparable that violates the Comparable contract. The previous
implementation silently ignored such a situation. If the previous
behavior is desired, you can use the new system
property java.util.Arrays.useLegacyMergeSort, to restore previous
mergesort behavior.
Nature of Incompatibility: behavioral
RFE: 6804124
For more detailed info, see the bug database reference here.
maybe you just have NaN values which you compare through Collections.sort(...), this has been a problem to me and I got that exception even having right implementation of compare(obj1, obj2) method! Check that!
I was able to solve this error cause it was a bug in jdk7.
here I found the solution:
"Comparison method violates its general contract!" - TimSort and GridLayout
Basically i just had to add the
JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"
to my jboss
Unfortunately, none of the solutions work for Android. TimSort is used deep in Android's ViewGroup relating to addChildrenForAccessibility that shows up under Java 7 & 8. No user code is involved in any comparison.
From other reports, it is related to having RelativeLayout with overlapping items as is commonly done. For example, a TextView that appears over an Image, or two items at the same location, where you only set one visible at a time.
https://code.google.com/p/android/issues/detail?id=55933
I've not found any way around the bug. You can't set a -Djava option in Android Studio or Eclipse (at least that I could find). Forcing use of Java 1.6 should work, but doesn't. Seems like Amazon's newer Fire tablets and phones are far more sensitive to this bug than other devices.
There are rumors Java 9 will have a fix such as a run-time option that works, but with a bug that's been around for years, I have doubts it will ever be fixed - especially considering the animosity between Oracle and Google. Any yes, perhaps the bug is really deep in the Android code and should be fixed there. With more than a billion devices out there, that's not a viable solution for all the existing devices.