Skip to content

Commit 0841ecc

Browse files
committed
Add unit tests
1 parent ef4bad8 commit 0841ecc

7 files changed

Lines changed: 114 additions & 5 deletions

File tree

Common/Data/Market/DataDictionary.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public bool Remove(KeyValuePair<Symbol, T> item)
146146
/// <returns>
147147
/// The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
148148
/// </returns>
149-
public int Count
149+
public override int Count
150150
{
151151
get { return _data.Count; }
152152
}

Common/Data/Slice.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public MarginInterestRates MarginInterestRates
171171
/// <summary>
172172
/// Gets the number of symbols held in this slice
173173
/// </summary>
174-
public virtual int Count
174+
public override int Count
175175
{
176176
get { return _data.Value.Count; }
177177
}

Common/ExtendedDictionary.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ namespace QuantConnect
3131
public abstract class ExtendedDictionary<TKey, TValue> : IExtendedDictionary<TKey, TValue>
3232
#pragma warning restore CA1708 // Identifiers should differ by more than case
3333
{
34+
/// <summary>
35+
/// Gets the number of elements contained in the dictionary
36+
/// </summary>
37+
public abstract int Count { get; }
38+
3439
/// <summary>
3540
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
3641
/// </summary>
@@ -55,6 +60,11 @@ public virtual void Clear()
5560
/// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null.</exception>
5661
public abstract bool TryGetValue(TKey key, out TValue value);
5762

63+
/// <summary>
64+
/// Checks if the dictionary contains the specified key.
65+
/// </summary>
66+
/// <param name="key">The key to locate in the dictionary</param>
67+
/// <returns>true if the dictionary contains an element with the specified key; otherwise, false.</returns>
5868
public virtual bool ContainsKey(TKey key)
5969
{
6070
return TryGetValue(key, out _);

Common/Securities/Positions/SecurityPositionGroupModel.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public class SecurityPositionGroupModel : ExtendedDictionary<PositionGroupKey, I
4242
/// </summary>
4343
protected virtual IPositionGroupBuyingPowerModel PositionGroupBuyingPowerModel { get; } = new SecurityPositionGroupBuyingPowerModel();
4444

45-
4645
/// <summary>
4746
/// Gets the set of currently resolved position groups
4847
/// </summary>
@@ -64,6 +63,11 @@ private set
6463
/// </summary>
6564
public bool IsOnlyDefaultGroups => Groups.IsOnlyDefaultGroups;
6665

66+
/// <summary>
67+
/// Gets the number of position groups in this collection
68+
/// </summary>
69+
public override int Count => Groups.Count;
70+
6771
/// <summary>
6872
/// Gets all the available position group keys
6973
/// </summary>

Common/Securities/SecurityManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public void CopyTo(KeyValuePair<Symbol, Security>[] array, int number)
171171
/// Count of the number of securities in the collection.
172172
/// </summary>
173173
/// <remarks>IDictionary implementation</remarks>
174-
public int Count
174+
public override int Count
175175
{
176176
get
177177
{

Common/Securities/SecurityPortfolioManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ public bool Contains(KeyValuePair<Symbol, SecurityHolding> pair)
189189
/// Count the securities objects in the portfolio.
190190
/// </summary>
191191
/// <remarks>IDictionary implementation calling the underlying Securities collection</remarks>
192-
public int Count
192+
public override int Count
193193
{
194194
get
195195
{

Tests/Common/ExtendedDictionaryTests.cs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
*/
1515

1616
using NUnit.Framework;
17+
using Python.Runtime;
1718
using QuantConnect.Statistics;
1819
using System.Collections.Generic;
20+
using System.Linq;
1921

2022
namespace QuantConnect.Tests.Common
2123
{
@@ -58,5 +60,98 @@ public void RunPythonDictionaryFeatureRegressionAlgorithm()
5860
parameter.ExpectedFinalStatus,
5961
initialCash: 100000);
6062
}
63+
64+
[Test]
65+
public void ExtendedDictionaryBehavesAsPythonDictionary()
66+
{
67+
using var _ = Py.GIL();
68+
69+
var module = PyModule.FromString("ExtendedDictionaryBehavesAsPythonDictionary",
70+
@"
71+
from QuantConnect.Tests.Common import ExtendedDictionaryTests
72+
73+
def contains(dictionary, key):
74+
return key in dictionary
75+
76+
def get(dictionary, key):
77+
return dictionary.get(key)
78+
79+
def keys(dictionary):
80+
return dictionary.keys()
81+
82+
def values(dictionary):
83+
return dictionary.values()
84+
85+
def pop(dictionary, key):
86+
return dictionary.pop(key)
87+
");
88+
89+
var dict = new TestDictionary
90+
{
91+
["a"] = 1,
92+
["b"] = 2,
93+
["c"] = 3
94+
};
95+
using var pyDict = dict.ToPython();
96+
97+
var expectedKeys = new[] { "a", "b", "c" };
98+
var keys = module.InvokeMethod("keys", pyDict).GetAndDispose<List<string>>();
99+
CollectionAssert.AreEquivalent(expectedKeys, keys);
100+
101+
var expectedValues = new[] { 1, 2, 3 };
102+
var values = module.InvokeMethod("values", pyDict).GetAndDispose<List<int>>();
103+
CollectionAssert.AreEquivalent(expectedValues, values);
104+
105+
foreach (var (key, value) in keys.Zip(values))
106+
{
107+
using var pyKey = key.ToPython();
108+
Assert.IsTrue(module.InvokeMethod("contains", pyDict, pyKey).As<bool>());
109+
Assert.AreEqual(value, module.InvokeMethod("get", pyDict, pyKey).As<int>());
110+
}
111+
112+
using var pyNonExistingKey = "d".ToPython();
113+
Assert.IsFalse(module.InvokeMethod("contains", pyDict, pyNonExistingKey).As<bool>());
114+
Assert.IsFalse(module.InvokeMethod("contains", pyDict, PyObject.None).As<bool>());
115+
116+
using var pyExistingKey = keys[0].ToPython();
117+
using var pyExistingValue = values[0].ToPython();
118+
var popped = module.InvokeMethod("pop", pyDict, pyExistingKey).As<int>();
119+
Assert.AreEqual(1, popped);
120+
Assert.IsFalse(module.InvokeMethod("contains", pyDict, pyExistingKey).As<bool>());
121+
}
122+
123+
public class TestDictionary : ExtendedDictionary<string, int>
124+
{
125+
private readonly Dictionary<string, int> _data = new();
126+
127+
public override int Count => _data.Count;
128+
129+
public override bool IsReadOnly => false;
130+
131+
public override int this[string key]
132+
{
133+
get => _data[key];
134+
set => _data[key] = value;
135+
}
136+
137+
protected override IEnumerable<string> GetKeys => _data.Keys;
138+
139+
protected override IEnumerable<int> GetValues => _data.Values;
140+
141+
public override bool TryGetValue(string key, out int value)
142+
{
143+
return _data.TryGetValue(key, out value);
144+
}
145+
146+
public override bool ContainsKey(string key)
147+
{
148+
return _data.ContainsKey(key);
149+
}
150+
151+
public override bool Remove(string key)
152+
{
153+
return _data.Remove(key);
154+
}
155+
}
61156
}
62157
}

0 commit comments

Comments
 (0)