Testing the process of assigning offers to a customer 2

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












I asked this question earlier: Testing the process of assigning offers to a customer. Following on from the answerers comprehensive response. I have attempted it again. Please see the test code below:



[TestFixture]
public class CustomerTest

private IList<IProduct> _products;
private Concor _concor;
private Chestnut _chestnut;

private IOfferCalculator _offerCalculator;

[OneTimeSetUp]
public void OneTimeSetUp()

_offerCalculator = new OfferCalculator();


[SetUp]
public void Setup()

_concor = new Concor();
_chestnut = new Chestnut();
_products = new List<IProduct>();
_products.Add(_concor);
_products.Add(_chestnut);


[Test]
public void Should_receive_a_for_concor()

var expectedConcor = new List<IProduct>();
expectedConcor.Add(_concor);
var gender = "F";
var expenditure = 1500M;
var customer = new Customer(gender,expenditure);
//Act
var eligibleProducts = customer.GetEligibleOffers(_offerCalculator, _products);
customer.AssignOffers(eligibleProducts.ToList());
//Assert
CollectionAssert.AreEqual(customer._assignedProducts, expectedConcor);




Here is the supporting code:



public class Concor : IProduct

//Added constants
private const decimal _expenditure =100;
private const string _gender = "F";

public bool IsEligible(string gender, decimal expenditure)

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




public class Chestnut : IProduct

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
private const decimal _expenditure = 100;
private const string _gender = "M";

public bool IsEligible(string gender, decimal expenditure)

//Remove magic string and magic decimal
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




//Replaced abstract class with interface
public interface IProduct

//This method now accepts parameters rather than an object
bool IsEligible(string gender, decimal expenditure);


public interface IOfferCalculator

//Renamed this method.
IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products);


public class Customer

public string Gender get; protected set;
public decimal Expenditure get; protected set;
public IList<IProduct> _assignedProducts = new List<IProduct>();

public Customer(string gender, decimal expenditure)

Gender = gender;
Expenditure = expenditure;


//Added this method as a result of refactoring AssignOffers.
public IEnumerable<IProduct> GetEligibleOffers(IOfferCalculator offerCalculator, IList<IProduct> products)

//Pass Gender and Expenditure instead of this object (Customer).
return offerCalculator.CalculateEligibility(Gender, Expenditure, products);


//Refactored this method.
public void AssignOffers(IList<IProduct> products)

foreach (var product in products)

_assignedProducts.Add(product);




public class OfferCalculator : IOfferCalculator

public IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products)

foreach (var product in products)

if (product.IsEligible(gender,expenditure))

yield return product;






I have included comments to show what I have changed.



I would like some feedback about the quality of the test. The company like to use BDD, however I am conscious that I asserting state rather than behaviour (arguing that I am testing calculations rather than orchestrations). I would also like some feedback about my use of the: OneTimeSetup attribute and Setup attribute. Also How would I test for a Chestnut? Add a new method or use an attribute for the test cases?







share|improve this question



















  • This looks much better now! ;-) You could put the F & M constants in a GenderCode class and name them accordingly (female/male).
    – t3chb0t
    Jan 27 at 19:21











  • Well, 100 is a constant now but the name, ouch! The name should explain why it's 100. Is it max or min or some other expenditure? Name it properly.
    – t3chb0t
    Jan 27 at 19:22











  • @t3chb0t, if I encapsulate the gender in a immutable GenderCode class then I will have to change the IProduct._gender constant to a read only property. I assume that is what you mean?
    – w0051977
    Jan 27 at 19:27











  • It can be either one (const/readonly) - the main point is, it should be as you've said immutable.
    – t3chb0t
    Jan 27 at 19:29










  • With regards to the constant names. I will change _expenditure to: _minExpenditure. . I think I will leave Gender as it is?
    – w0051977
    Jan 27 at 19:33
















up vote
1
down vote

favorite












I asked this question earlier: Testing the process of assigning offers to a customer. Following on from the answerers comprehensive response. I have attempted it again. Please see the test code below:



[TestFixture]
public class CustomerTest

private IList<IProduct> _products;
private Concor _concor;
private Chestnut _chestnut;

private IOfferCalculator _offerCalculator;

[OneTimeSetUp]
public void OneTimeSetUp()

_offerCalculator = new OfferCalculator();


[SetUp]
public void Setup()

_concor = new Concor();
_chestnut = new Chestnut();
_products = new List<IProduct>();
_products.Add(_concor);
_products.Add(_chestnut);


[Test]
public void Should_receive_a_for_concor()

var expectedConcor = new List<IProduct>();
expectedConcor.Add(_concor);
var gender = "F";
var expenditure = 1500M;
var customer = new Customer(gender,expenditure);
//Act
var eligibleProducts = customer.GetEligibleOffers(_offerCalculator, _products);
customer.AssignOffers(eligibleProducts.ToList());
//Assert
CollectionAssert.AreEqual(customer._assignedProducts, expectedConcor);




Here is the supporting code:



public class Concor : IProduct

//Added constants
private const decimal _expenditure =100;
private const string _gender = "F";

public bool IsEligible(string gender, decimal expenditure)

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




public class Chestnut : IProduct

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
private const decimal _expenditure = 100;
private const string _gender = "M";

public bool IsEligible(string gender, decimal expenditure)

//Remove magic string and magic decimal
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




//Replaced abstract class with interface
public interface IProduct

//This method now accepts parameters rather than an object
bool IsEligible(string gender, decimal expenditure);


public interface IOfferCalculator

//Renamed this method.
IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products);


public class Customer

public string Gender get; protected set;
public decimal Expenditure get; protected set;
public IList<IProduct> _assignedProducts = new List<IProduct>();

public Customer(string gender, decimal expenditure)

Gender = gender;
Expenditure = expenditure;


//Added this method as a result of refactoring AssignOffers.
public IEnumerable<IProduct> GetEligibleOffers(IOfferCalculator offerCalculator, IList<IProduct> products)

//Pass Gender and Expenditure instead of this object (Customer).
return offerCalculator.CalculateEligibility(Gender, Expenditure, products);


//Refactored this method.
public void AssignOffers(IList<IProduct> products)

foreach (var product in products)

_assignedProducts.Add(product);




public class OfferCalculator : IOfferCalculator

public IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products)

foreach (var product in products)

if (product.IsEligible(gender,expenditure))

yield return product;






I have included comments to show what I have changed.



I would like some feedback about the quality of the test. The company like to use BDD, however I am conscious that I asserting state rather than behaviour (arguing that I am testing calculations rather than orchestrations). I would also like some feedback about my use of the: OneTimeSetup attribute and Setup attribute. Also How would I test for a Chestnut? Add a new method or use an attribute for the test cases?







share|improve this question



















  • This looks much better now! ;-) You could put the F & M constants in a GenderCode class and name them accordingly (female/male).
    – t3chb0t
    Jan 27 at 19:21











  • Well, 100 is a constant now but the name, ouch! The name should explain why it's 100. Is it max or min or some other expenditure? Name it properly.
    – t3chb0t
    Jan 27 at 19:22











  • @t3chb0t, if I encapsulate the gender in a immutable GenderCode class then I will have to change the IProduct._gender constant to a read only property. I assume that is what you mean?
    – w0051977
    Jan 27 at 19:27











  • It can be either one (const/readonly) - the main point is, it should be as you've said immutable.
    – t3chb0t
    Jan 27 at 19:29










  • With regards to the constant names. I will change _expenditure to: _minExpenditure. . I think I will leave Gender as it is?
    – w0051977
    Jan 27 at 19:33












up vote
1
down vote

favorite









up vote
1
down vote

favorite











I asked this question earlier: Testing the process of assigning offers to a customer. Following on from the answerers comprehensive response. I have attempted it again. Please see the test code below:



[TestFixture]
public class CustomerTest

private IList<IProduct> _products;
private Concor _concor;
private Chestnut _chestnut;

private IOfferCalculator _offerCalculator;

[OneTimeSetUp]
public void OneTimeSetUp()

_offerCalculator = new OfferCalculator();


[SetUp]
public void Setup()

_concor = new Concor();
_chestnut = new Chestnut();
_products = new List<IProduct>();
_products.Add(_concor);
_products.Add(_chestnut);


[Test]
public void Should_receive_a_for_concor()

var expectedConcor = new List<IProduct>();
expectedConcor.Add(_concor);
var gender = "F";
var expenditure = 1500M;
var customer = new Customer(gender,expenditure);
//Act
var eligibleProducts = customer.GetEligibleOffers(_offerCalculator, _products);
customer.AssignOffers(eligibleProducts.ToList());
//Assert
CollectionAssert.AreEqual(customer._assignedProducts, expectedConcor);




Here is the supporting code:



public class Concor : IProduct

//Added constants
private const decimal _expenditure =100;
private const string _gender = "F";

public bool IsEligible(string gender, decimal expenditure)

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




public class Chestnut : IProduct

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
private const decimal _expenditure = 100;
private const string _gender = "M";

public bool IsEligible(string gender, decimal expenditure)

//Remove magic string and magic decimal
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




//Replaced abstract class with interface
public interface IProduct

//This method now accepts parameters rather than an object
bool IsEligible(string gender, decimal expenditure);


public interface IOfferCalculator

//Renamed this method.
IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products);


public class Customer

public string Gender get; protected set;
public decimal Expenditure get; protected set;
public IList<IProduct> _assignedProducts = new List<IProduct>();

public Customer(string gender, decimal expenditure)

Gender = gender;
Expenditure = expenditure;


//Added this method as a result of refactoring AssignOffers.
public IEnumerable<IProduct> GetEligibleOffers(IOfferCalculator offerCalculator, IList<IProduct> products)

//Pass Gender and Expenditure instead of this object (Customer).
return offerCalculator.CalculateEligibility(Gender, Expenditure, products);


//Refactored this method.
public void AssignOffers(IList<IProduct> products)

foreach (var product in products)

_assignedProducts.Add(product);




public class OfferCalculator : IOfferCalculator

public IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products)

foreach (var product in products)

if (product.IsEligible(gender,expenditure))

yield return product;






I have included comments to show what I have changed.



I would like some feedback about the quality of the test. The company like to use BDD, however I am conscious that I asserting state rather than behaviour (arguing that I am testing calculations rather than orchestrations). I would also like some feedback about my use of the: OneTimeSetup attribute and Setup attribute. Also How would I test for a Chestnut? Add a new method or use an attribute for the test cases?







share|improve this question











I asked this question earlier: Testing the process of assigning offers to a customer. Following on from the answerers comprehensive response. I have attempted it again. Please see the test code below:



[TestFixture]
public class CustomerTest

private IList<IProduct> _products;
private Concor _concor;
private Chestnut _chestnut;

private IOfferCalculator _offerCalculator;

[OneTimeSetUp]
public void OneTimeSetUp()

_offerCalculator = new OfferCalculator();


[SetUp]
public void Setup()

_concor = new Concor();
_chestnut = new Chestnut();
_products = new List<IProduct>();
_products.Add(_concor);
_products.Add(_chestnut);


[Test]
public void Should_receive_a_for_concor()

var expectedConcor = new List<IProduct>();
expectedConcor.Add(_concor);
var gender = "F";
var expenditure = 1500M;
var customer = new Customer(gender,expenditure);
//Act
var eligibleProducts = customer.GetEligibleOffers(_offerCalculator, _products);
customer.AssignOffers(eligibleProducts.ToList());
//Assert
CollectionAssert.AreEqual(customer._assignedProducts, expectedConcor);




Here is the supporting code:



public class Concor : IProduct

//Added constants
private const decimal _expenditure =100;
private const string _gender = "F";

public bool IsEligible(string gender, decimal expenditure)

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




public class Chestnut : IProduct

//Added constants. Not sure whether they should be private or public. Surely they should be private and not public just so users
//of the Domsain Model can see them?
private const decimal _expenditure = 100;
private const string _gender = "M";

public bool IsEligible(string gender, decimal expenditure)

//Remove magic string and magic decimal
if (expenditure > _expenditure && gender == _gender)

return true;

else

return false;




//Replaced abstract class with interface
public interface IProduct

//This method now accepts parameters rather than an object
bool IsEligible(string gender, decimal expenditure);


public interface IOfferCalculator

//Renamed this method.
IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products);


public class Customer

public string Gender get; protected set;
public decimal Expenditure get; protected set;
public IList<IProduct> _assignedProducts = new List<IProduct>();

public Customer(string gender, decimal expenditure)

Gender = gender;
Expenditure = expenditure;


//Added this method as a result of refactoring AssignOffers.
public IEnumerable<IProduct> GetEligibleOffers(IOfferCalculator offerCalculator, IList<IProduct> products)

//Pass Gender and Expenditure instead of this object (Customer).
return offerCalculator.CalculateEligibility(Gender, Expenditure, products);


//Refactored this method.
public void AssignOffers(IList<IProduct> products)

foreach (var product in products)

_assignedProducts.Add(product);




public class OfferCalculator : IOfferCalculator

public IEnumerable<IProduct> CalculateEligibility(string gender, decimal expenditure, IList<IProduct> products)

foreach (var product in products)

if (product.IsEligible(gender,expenditure))

yield return product;






I have included comments to show what I have changed.



I would like some feedback about the quality of the test. The company like to use BDD, however I am conscious that I asserting state rather than behaviour (arguing that I am testing calculations rather than orchestrations). I would also like some feedback about my use of the: OneTimeSetup attribute and Setup attribute. Also How would I test for a Chestnut? Add a new method or use an attribute for the test cases?









share|improve this question










share|improve this question




share|improve this question









asked Jan 27 at 19:18









w0051977

389112




389112











  • This looks much better now! ;-) You could put the F & M constants in a GenderCode class and name them accordingly (female/male).
    – t3chb0t
    Jan 27 at 19:21











  • Well, 100 is a constant now but the name, ouch! The name should explain why it's 100. Is it max or min or some other expenditure? Name it properly.
    – t3chb0t
    Jan 27 at 19:22











  • @t3chb0t, if I encapsulate the gender in a immutable GenderCode class then I will have to change the IProduct._gender constant to a read only property. I assume that is what you mean?
    – w0051977
    Jan 27 at 19:27











  • It can be either one (const/readonly) - the main point is, it should be as you've said immutable.
    – t3chb0t
    Jan 27 at 19:29










  • With regards to the constant names. I will change _expenditure to: _minExpenditure. . I think I will leave Gender as it is?
    – w0051977
    Jan 27 at 19:33
















  • This looks much better now! ;-) You could put the F & M constants in a GenderCode class and name them accordingly (female/male).
    – t3chb0t
    Jan 27 at 19:21











  • Well, 100 is a constant now but the name, ouch! The name should explain why it's 100. Is it max or min or some other expenditure? Name it properly.
    – t3chb0t
    Jan 27 at 19:22











  • @t3chb0t, if I encapsulate the gender in a immutable GenderCode class then I will have to change the IProduct._gender constant to a read only property. I assume that is what you mean?
    – w0051977
    Jan 27 at 19:27











  • It can be either one (const/readonly) - the main point is, it should be as you've said immutable.
    – t3chb0t
    Jan 27 at 19:29










  • With regards to the constant names. I will change _expenditure to: _minExpenditure. . I think I will leave Gender as it is?
    – w0051977
    Jan 27 at 19:33















This looks much better now! ;-) You could put the F & M constants in a GenderCode class and name them accordingly (female/male).
– t3chb0t
Jan 27 at 19:21





This looks much better now! ;-) You could put the F & M constants in a GenderCode class and name them accordingly (female/male).
– t3chb0t
Jan 27 at 19:21













Well, 100 is a constant now but the name, ouch! The name should explain why it's 100. Is it max or min or some other expenditure? Name it properly.
– t3chb0t
Jan 27 at 19:22





Well, 100 is a constant now but the name, ouch! The name should explain why it's 100. Is it max or min or some other expenditure? Name it properly.
– t3chb0t
Jan 27 at 19:22













@t3chb0t, if I encapsulate the gender in a immutable GenderCode class then I will have to change the IProduct._gender constant to a read only property. I assume that is what you mean?
– w0051977
Jan 27 at 19:27





@t3chb0t, if I encapsulate the gender in a immutable GenderCode class then I will have to change the IProduct._gender constant to a read only property. I assume that is what you mean?
– w0051977
Jan 27 at 19:27













It can be either one (const/readonly) - the main point is, it should be as you've said immutable.
– t3chb0t
Jan 27 at 19:29




It can be either one (const/readonly) - the main point is, it should be as you've said immutable.
– t3chb0t
Jan 27 at 19:29












With regards to the constant names. I will change _expenditure to: _minExpenditure. . I think I will leave Gender as it is?
– w0051977
Jan 27 at 19:33




With regards to the constant names. I will change _expenditure to: _minExpenditure. . I think I will leave Gender as it is?
– w0051977
Jan 27 at 19:33















active

oldest

votes











Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186148%2ftesting-the-process-of-assigning-offers-to-a-customer-2%23new-answer', 'question_page');

);

Post as a guest



































active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes










 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186148%2ftesting-the-process-of-assigning-offers-to-a-customer-2%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Chat program with C++ and SFML

Read an image with ADNS2610 optical sensor and Arduino Uno

Read files from a directory using Promises