Code Monkey home page Code Monkey logo

stateprinter's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stateprinter's Issues

Tests don't run in Visual Studio 2017

When attempting to run the tests in VS 2017 (Enterprise v15.9.2) it gives the following error when attempting to run all tests.
As suggested, I upgraded the test project to Framework v4.0 and all tests could be run.

[15/01/2019 13:49:51 Informational] ------ Discover test started ------
[15/01/2019 13:49:51 Error] Microsoft.VisualStudio.TestPlatform.ObjectModel.TestPlatformException: Framework35 is not supported. For projects targeting .Net Framework 3.5, please use Framework40 to run tests in CLR 4.0 "compatibility mode".
   at Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers.TestRequestManager.UpdateRunSettingsIfRequired(String runsettingsXml, List`1 sources, String& updatedRunSettingsXml)
   at Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers.TestRequestManager.DiscoverTests(DiscoveryRequestPayload discoveryPayload, ITestDiscoveryEventsRegistrar discoveryEventsRegistrar, ProtocolConfig protocolConfig)
   at Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.<>c__DisplayClass20_0.<StartDiscovery>b__0()
[15/01/2019 13:49:51 Informational] ========== Discover test finished: 0 found (0:00:00.3566916) ==========
[15/01/2019 13:49:57 Informational] ------ Run test started ------
[15/01/2019 13:49:57 Error] Microsoft.VisualStudio.TestPlatform.ObjectModel.TestPlatformException: Framework35 is not supported. For projects targeting .Net Framework 3.5, please use Framework40 to run tests in CLR 4.0 "compatibility mode".
   at Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers.TestRequestManager.UpdateRunSettingsIfRequired(String runsettingsXml, List`1 sources, String& updatedRunSettingsXml)
   at Microsoft.VisualStudio.TestPlatform.CommandLine.TestPlatformHelpers.TestRequestManager.RunTests(TestRunRequestPayload testRunRequestPayload, ITestHostLauncher testHostLauncher, ITestRunEventsRegistrar testRunEventsRegistrar, ProtocolConfig protocolConfig)
   at Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.<>c__DisplayClass19_0.<StartTestRun>b__0()
[15/01/2019 13:49:57 Informational] ========== Run test finished: 0 run (0:00:00.026926) ==========

Field harvester factory method

We need an easy way to create an anonymous field harvester. The configuration should have an AddHarvester taking two lambdas as argument which should create an instance of a new AnonymousFieldHarveater

Properties that throw exceptions are not handled

If PublicFieldsAndPropertiesHarvester is used, and a property access attempt throws an exception, the exception bubbles up to the top and cannot be handled, as in the code below.

It would be better to at least allow the user to have the exception returned as the value for that property instead.

System.Reflection.TargetInvocationException occurred
  HResult=-2146232828
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
       at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
       at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
       at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
       at StatePrinter.FieldHarvesters.HarvestHelper.<>c__DisplayClass9.<GetFieldsAndProperties>b__6(Object o)
       at StatePrinter.Introspection.IntroSpector.IntrospectComplexType(Object source, Field field, Type sourceType)
       at StatePrinter.Introspection.IntroSpector.Introspect(Object source, Field field)
       at StatePrinter.Introspection.IntroSpector.PrintObject(Object objectToPrint, String rootname)
       at StatePrinter.Stateprinter.PrintObject(Object objectToPrint, String rootname)
  InnerException: 
       HResult=-2146233088
       Message=An identifier field is not present in this artifact's field collection.
       Source=kCura.Relativity.Client
       StackTrace:
            at MyApplication.DTOs.Artifact.get_TextIdentifier()
       InnerException: 

Support printing database state

As of now, Stateprinter has focused on printing state from memory. There is nothing wrong with printing state read from a subset of a database. Eg.

printer.PrintTable("SELECT TOP y x,y,z FROM a WHERE b", "rows of a", conn)
printer.PrintTable(string sql, string rootname, Connection conn)

or

printer.PrintTable(IQueryable<T> q, string rootname)

possibly for the method taking sql as an argument, we need an overload taking a transaction such that we can read data that is not yet committed (and might need to be rolled back, eg. in a unit test)

Support custom ordering of collections

Enhance the IntroSpector class to support configurable ordering of collections. The configuration should work in the same "stacking" manner as the FieldHarvesters.

Also a standard implementation for IEnumerable Where T : IComparable should be made.

Obsolete include projection

When #17 is completed,

  • deprecate include filtering and update documentation to use the new map functionality
  • document the map-functionality

note use the feature/mapprojection branch

CultureInfo is not respected

On the master branch in the CultureTests.CultureDependentPrinting_us test, the test fails on my machine with the result:

String lengths are both 21. Strings differ at index 1.
Expected: "2/28/2010 10:10:59 PM"
But was:  "28-Feb-10 10:10:59 PM"

My machine uses the Thailand culture.

Path-based references

The current method used for avoiding cycles and duplicate printing, using index-based references, is not serving us well in the use case of StatePrinter combined with ApprovalTests as a way of ensuring object state doesn't change over time. If one new reference is added or removed somewhere 'early' in the object, the indices of all following references are incremented, making it very difficult to tell what really changed. For example, if we have this printed object:

Root = new RootObject()
{
    _container = new Container(), ref: 1
    {
        _objects = new List<Object>()
        {
            [0] = new A(), ref: 0
            {
            }
        }
        _a = -> 0
    }
    _otherObject = new OtherObject()
    {
        _container = -> 1
    }
    [lots more objects with lots more references]
}

If the reference to the object A() is removed, all following reference indices will be decremented. When looking at the change to the object, there will be a diff for each line in the file that previously had a reference on it. For very large files (1000s of lines), it becomes tedious to spot the real change, especially if there are other real changes later in the file.

I propose a 'path-based' way of referencing instead. The above example would then look something like this:

Root = new RootObject()
{
    _container = new Container()
    {
        _objects = new List<Object>()
        {
            [0] = new A()
            {
            }
        }
        _a = -> Root._container._objects[0]
    }
    _otherObject = new OtherObject()
    {
        _container = -> Root._container
    }
    [lots more objects with lots more references]
}

With this approach, changes wouldn't ripple to unrelated objects like described above.

I'm not sure if it's better to do an absolute path from root (as shown above) or a relative path. Maybe that could be user-configurable. With relative paths, the above references could then look something like this._objects[0] and ^._container.

If I get the time, I might take a first stab at implementing this. I imagine it will require some fairly substantial changes in Introspector.

Rolling guid-ValueConverter

to simplify unit testing with data containing guids, we need to ensure the guid values are stable across executions.

Thus a valueconverter for guids. converting them into 000001, 000002, ... as they meet is needed. A dictionary should hold converted values to ensure the same guid printed multiple times is printed with its new value.

Get enspired from the existing GuidValueConverter

Also documentation on how to use it in unit testing is needed

Output valid C#

This would be so useful to me... if only it could output valid C# code! Currently, I have to print the object and then mess around with it to get it to compile. This would be such an awesome feature. Obviously cycles could not be supported.

Weird output of data structure

curly style output of

public class TagsCollection
{
    public Dictionary<string, List<string>> Pages = new Dictionary<string, List<string>>();

    public void Add(string tag, string url)
    {
        List<string> urls;
        if (!Pages.TryGetValue(tag, out urls))
            Pages.Add(tag, urls = new List<string>());
        urls.Add(url);
    }
}

becomes

var expected = @"new TagsCollection()
{
    Pages[""Design""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[""SOLID""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[1] = ""BookReviews\Adaptive Code via CS.md""
    Pages[""Single_Responsibility_Principle""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[""Design_Pattern""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[""Decorator""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[""Wrapper""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[""Cache""] = new List<String>()
    Pages[0] = ""Articles\Design\MalleableCodeUsingDecorators.md""
    Pages[""Book_Review""] = new List<String>()
    Pages[0] = ""BookReviews\Adaptive Code via CS.md""
}";

Filtering in the debugger output

A filtering mechanism needs be implemented to reduce the amount of information displayed in the debugger window. Maybe a textbox for inputting xpath could be a solution

Ensure correct Json format

The JsonSerializer can be used for generating json text from an object graph (with no cycles). Possibly this could be used as a reference solution and compared against stateprinter's way of generating json

Make error message configurable upon assertion failiure

Currently, the assert error message is hard-coded. We need to introduce an abstraction that given the "new" and "old" values used in the assert along with the message provided in the assert and the escaped "new suggested value" for the assert-rewrite

e.g. something

string CreateAssertMessage(
  string actual, 
  string oldExpected, 
  string escapedNewExpected)

and provide a default behaviour that shows the full old and new values for the assert

The CreateAssertMessage should be configurable through the Configuration class.

Problem with rewriting expected values if value contains brackets.

Current version does not correctly rewrite expected value, if given value contains brackets.
Example:

string expected = @"new List<Int32>()
{
    [0] = 1
    [1] = 2
    [2] = 3
    [3] = 4
}";
TestHelper.Assert().PrintEquals(expected, actual);

I created a pull request with proposed fix: #49

StatePrinter throws if GetEnumerator() throws (e.g. on default ImmutableArray)

StatePrinter version: 3.0.1

class Foo
{
  public readonly ImmutableArray<int> arr = default;
}

[TestMethod]
public void Test()
{
  var printer = new Stateprinter(ConfigurationHelper.GetStandardConfiguration());

  Console.WriteLine(printer.PrintObject(new Foo()));
}

Throws:

System.InvalidOperationException: This operation cannot be performed on a default instance of ImmutableArray<T>.  Consider initializing the array, or checking the ImmutableArray<T>.IsDefault property.
   at System.Collections.Immutable.ImmutableArray`1.ThrowInvalidOperationIfNotInitialized()
   at System.Collections.Immutable.ImmutableArray`1.System.Collections.IEnumerable.GetEnumerator()
   at StatePrinting.Introspection.IntroSpector.IntrospectIEnumerable(Object source, Field field)
   at StatePrinting.Introspection.IntroSpector.Introspect(Object source, Field field)
   at StatePrinting.Introspection.IntroSpector.IntrospectComplexType(Object source, Field field, Type sourceType)
   at StatePrinting.Introspection.IntroSpector.Introspect(Object source, Field field)
   at StatePrinting.Introspection.IntroSpector.PrintObject(Object objectToPrint, String rootname)
   at StatePrinting.Stateprinter.PrintObject(Object objectToPrint, String rootname)

Possible fixes (not mutually exclusive):

  • Catch exceptions thrown by GetEnumerator() (possibly slow)
  • Special-case known types like ImmutableArray<> having this behavior (in this case, check the IsDefault property)
  • Check all values of IEnumerable value types for equality to the default value (but their Equals implementation often throws too; would probably need an unsafe "raw" equality test)

caching the configuration

The configuration class needs a cache. construct the cache as a wrapper for the configuration caching the result of the wrapper. Eg, calls to TryGetValueConverter and TryGetFieldHarvester

Debug assistance window

Implement a multi-panel wpf "editor" that supports xml-folding and raw text, maybe even show images produced by graphwiz.

the idea is to insert printer.Debug.PrintObject(o) and this editor will open, or if already open, will add a new pane. Thereby we enable better debugging sessions for programmers dealing with a lot of data.

this is advantageous over the normal profiler view in

  1. you can search the content of the panel
  2. you have several panels potentially, which show the development of state

I think its best not to use 3rd party plugins for this in order to keep dependencies at 0 for StatePrinter

Root name fixing

The way the root name is passed down to the introspector as a fieldname assumed that there would be a sane field to attach this name to. Im not convinced this is the case when the root object is a dictionary of simple types or an enumerable. eg. an empty one. how these are printed do not necesarily leave room for the field name.

maybe the root name should be applied explicitly after the introspection rather than pushing down the root name to the first field. This may break with existing token production.

make support for combinatorial input to tests

since we can autogenerate asserts, we should provide a helper architecture to provide combinatorial input to test methods, join their result and assert against that.

e.g. a method taking two bools as arguments, should get 4 inputs, each of which must be applied

but also composite types must be creatable in the same manner, with plugability such that the end user can specify how to create bespoke types. Eg a class Person with a first name, surname, zip code and address

maybe provide a testresultclass, that is more or less an array of strings which are stateprinted actual results.

proposal: Change minimum .net supported version

So the current min is .net 3.5. which was released ~11 years ago.

Perhaps the new min could be 4.5.2, released ~4 years ago ?

I know this is a breaking change, but people still using 3.5 can stay on the old nuget until they can move on to 4.5.2.

related to: #52

Ambigous constructors prevent StatePrinter from being used by VB.Net

StatePrinter has two constructors: Stateprinter and StatePrinter (deprecated)

Believe it or not (took me a while), when viewed from VB.Net, these are ambiguous because VB is case insensitive.

AFAICS, this completely prevents SP from being used from VB without the developer writing her own C# wrapper class to hide the original SP constructors.

Please see my question at StackOverflow which gives a bit more detail: http://stackoverflow.com/questions/35092412/using-stateprinter-from-vb-rather-than-c-sharp-to-implement-tostring

The simplest solution would be to drop the old constructor altogether and beware case-only differences in the future. If you can't do that for backward compatibility reasons, perhaps you could cut a VB-only, futures-only version.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.