-
Notifications
You must be signed in to change notification settings - Fork 340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why does AF lack support for modifying elements in a collection? #361
Comments
As that answer explains: there are already language constructs available for such operations, so why should AutoFixture contain an ad hoc, informally-specified, bug-ridden, slow implementation of half of C# (or VB.NET, or F#)?
This makes me curious, though. Why do you think that this is a requirement for making AutoFixture useful? What are you trying to do with it? FWIW, I've written thousands of tests using AutoFixture since it was created in early 2009, and while I've occasionally had the need to manipulate collection elements in a single test case here and there, I don't think I've ever had the need to do it in a Customization... so that's the reason I'm curious about your scenario. |
AF has no support from documentation or blog posts, from what I can tell, to create a customization that modifies a subset of items in a collection so that calling CreateMany returns a list of type T which contain items that adhear to certain criteria. Without of course, defeating the purpose of using AF to begin with and creating a method which just returns that list, which I of course now need to main. What I want is to create 10 orders, with all data randomly mocked, like AF does, but say that certain orders contain certain criteria, thats set inside a customization, so it is reused across all tests using that customization. That aside, now running into issues where the most basic 'Create' fails. Class with a Base Abstract Class. Call Create on the subclass. Get error about:
I think I'll just flag using AF, already running into so many roadblocks with it for trivial things. For what its worth, the code to create that error:
Where Order is:
|
This is crystal clear: I understand what you want to do, but I don't understand why you want to do it. Your original question was, "Why does AF lack support for modifying elements in a collection?", and my original answer, both here, and on your recent Stack Overflow question is that the reason AutoFixture doesn't have that, is because you shouldn't need it. I may be wrong; that's happened before. That's the reason I ask you about your specific requirements, instead of your general requirements, because in general I've never had the need to do something like that, and I've been using AutoFixture for 6+ years... I'd like to understand why you want to do something like that. Can you provide more details about your specific issue? I've tried the following, but can't reproduce the error you're reporting. public class NodeBase { }
public class Order : NodeBase { }
public class Tests
{
[Fact]
public void Repro()
{
var fixture = new Fixture();
var order = fixture.Create<Order>(); // Doesn't throw
}
} |
So we have a legacy system, where we have a God class called Delivery, Order, Version, Storyboard, File, etc. 60% of the system relies on Order/Version, based on a discriminator. A lot of code requires pulling this together at the same time. So I have: 10 Nodes Then the other 25 fields are randomly generated. So I want to avoid having to manually create lots of data, but have control over the relationships, and some specific settings that should be the same across the large majority of tests. Now inside the tests I have no problem saying: orders[0].Setting... = ... some specific test scenario The issue is setting up all the initial data. So I want to pull that into a customization and say right. For most of our tests which require this, its pre-configured to a valid scenario. And we override for test cases. The second issue around the base-type and recursion. We support unlimited number of child nodes. So all nodes have a parent.
This I cannot get working. |
Thank you for sharing some specifics about your motivation for wanting to do what you ask about. That should be possible. Here's a small proof of concept: public class Node
{
public int ParentId;
public int Id;
public int Type;
public string Delivery;
public string Order;
public string Version;
}
public class NodeCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register(() => CreateNodes(fixture));
}
private static List<Node> CreateNodes(IFixture fixture)
{
var nodes = fixture.CreateMany<Node>(10).ToList();
nodes[0].ParentId = 0; nodes[0].Id = 1; nodes[0].Type = 1;
nodes[1].ParentId = 1; nodes[1].Id = 2; nodes[1].Type = 2;
nodes[2].ParentId = 1; nodes[2].Id = 3; nodes[2].Type = 2;
nodes[3].ParentId = 1; nodes[3].Id = 4; nodes[3].Type = 2;
nodes[4].ParentId = 0; nodes[4].Id = 5; nodes[4].Type = 1;
nodes[5].ParentId = 5; nodes[5].Id = 6; nodes[5].Type = 2;
nodes[6].ParentId = 5; nodes[6].Id = 7; nodes[6].Type = 2;
nodes[7].ParentId = 5; nodes[7].Id = 8; nodes[7].Type = 2;
return nodes;
}
}
public class Tests
{
[Fact]
public void CreateNodesUsingCustomizedFixture()
{
var fixture = new Fixture().Customize(new NodeCustomization());
var nodes = fixture.Create<List<Node>>();
Assert.Equal(0, nodes[0].ParentId);
Assert.Equal(1, nodes[1].ParentId);
Assert.Equal(1, nodes[2].ParentId);
Assert.Equal(1, nodes[3].ParentId);
Assert.Equal(0, nodes[4].ParentId);
Assert.Equal(5, nodes[5].ParentId);
Assert.Equal(5, nodes[6].ParentId);
Assert.Equal(5, nodes[7].ParentId);
Assert.NotEqual(default(string), nodes[0].Delivery);
// etc.
}
} The fixture.Register<Node[]>(() => CreateNodes(fixture).ToArray()); With that out of the way, let's revisit the reason AutoFixture doesn't have a Domain-Specific Language for this sort of thing. First, why should you be forced to learn a new, specialised API for this sort of thing, when you can already use your existing knowledge of C# (or VB.NET, or F#)? As you can see, the Second, AutoFixture was originally created as a tool for Test-Driven Development. It's always a good sign if a piece of software can be picked up and used by other people in ways the original creators hadn't predicted, so I think it's cool if you would like to use it with a legacy system. However, the reason that AutoFixture doesn't have explicit support for addressing issues like the above is that it's an opinionated library: it tries hard to make it easy for you to do the right thing, and conversely, wants to make it hard for you to do the wrong things. The design you sketch above looks like it could be improved. I do realise that you explained that it's a legacy system, and you probably can't address the design issues, which is also the reason I started this particular reply with a possible way to address the issue. However, it'd be much better not having that issue at all, and that's the reason AutoFixture doesn't have an API for that sort of thing. The code you supplied does throw an exception, but not the exception you originally reported. Can we take that in another thread? Preferably on Stack Overflow. |
Thanks @ploeh. Ok so I missed Register completely. I tried I thought: "Ok, it's either gonna be in the API, or allow me modify it and store it" but I couldn't do either, I did look through blog posts and doco but never found what I was looking for. Our application is about 8 years old, and we do TDD, but with so much legacy code we looked at AF to help facilitate some of the legacy code issues we have in unit tests. (we have around 10k unit tests, so there's lots of duplication in setup of objects) I have no problems with AF being an opinionated library, but if I read in the doco what you said above i would be like "OH ok cool, no API for it, can still do it, just need to do it myself, no worries" but lacking both got me frustrated! Can move to SO, will do on Monday. |
FWIW, if I could do it all over again today, I would have put the documentation in an easier-to-find place, rather than scattered around in blog posts etc... |
Indeed, I think AtomEventStore's wiki is a good example. |
@moodmosaic, well, it's the best I could come up with, but it's coupled to GitHub, so that could become an issue... Also, there are issues with GitHub wikis that I'm not completely happy with. |
@ploeh A good alternative can be Read the Docs which has PDF Generation, full-text search, and more. |
@ploeh what are you not happy with. I think Nancy wiki is pretty decent. And while lacking I think I did a decent job with Snow. The wiki is easier to work with when you pull the repo down. Then you can add images. |
@phillip-haydon, TBH, I can't remember if there was anything besides this, but I dislike that the Pages list on the right is a flat list without any sort of structure. See e.g. https://github.com/GreanTech/AtomEventStore/wiki |
Is not flat :D |
That's a "side bar" though (which looks nice!)
|
That does look nice - I wasn't aware of that feature. Thanks for the tip 👍 |
@phillip-haydon, did you get an answer to your original question? If not, how can we help you? If so, can we close the issue? |
Sorry, I got pulled onto some other stuff and haven't had a chance to go back to the original issue. I'll raise an issue on Github when I get to it again. |
In regards to this SO question:
http://stackoverflow.com/questions/19286476/autofixture-how-do-i-assign-a-property-on-only-a-subrange-of-items-in-a-list
Why does AF lack support for this sort of thing. It makes it impossible (from what I can tell) to do this stuff in a customization, meaning the benefit of autofixture is completely lost.
The text was updated successfully, but these errors were encountered: