Giter VIP home page Giter VIP logo

testingpatterns's Introduction

TestingPatterns

This project is to record and share patterns and libraries that make testing

  • easier
  • more resilient
  • more powerful
  • more descriptive

As a result, it also demonstrates many other patterns and libraries that enable good development practices.

Here is the presentation the triggered the project: https://20xtesting.slides.spencerfarley.com

Here is a presentation that describes the design philosphies: https://1drv.ms/b/s!AjVvNQ4uturOby6OwKMFpMUlMqA

This project is very much overkill for a Todo list. However, the overkill is to demonstrate the patterns in a way that can easily be transfered to a large project

Testing Patterns

  • Dependency Injection
  • DataPrep (centralized test data generators)
  • ConfigWrappers //pending
  • Inconclusive tests to mark untested code
  • Test name modification for test runner (display extra info without manually adding it to each test name)
  • Unit/Integration test reuse

Testing Libraries

Example Build Pipeline: https://spencerfarley.visualstudio.com/TestingPatterns/

testingpatterns's People

Contributors

farlee2121 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

testingpatterns's Issues

Special Charater Testings

Make it easy to test for simple free text vulnerabilities like special characters, sql injections, etc.

Could add a method to the builder that adds the text to every string type.

May want to look at running different theories (parameterized unit tests) for different vulnerabilities

Builder Patterns for more flexible dataprep

A builder could enable complex data creation while keeping each custom dimension more independent (fewer parameter in each signature, mix and match scenarios).

Bogus already works as a builder, but is very generic and requires relatively verbose configuration (*.RuleFor( prop => prop.Rulestuff...))

Key concerns.

  • I want to keep my ability to create named scenarios
  • keep overall specification short
  • Keep ability for instance configuration (like persists to DB or not)
    • no static extentions
  • keep my orchestration layer that allows joint configuration and one handle to data preps
    • This means no creating an instance for every case (like with bogus)

Possible solutions

  • use a builder behind a normal dataprep (add complexity and extra definition, but fits all requirements)
  • Treat my builder like it's immutable or like a c# 8 record (which has the .With() method to create modified instances)
    • This could possibly chew memory

F# backend

Create an experimental version of the app with F# to see how the architecture and patterns translate into a functional language.

Functional languages enforce many of the practices I use by convention. It may make sense to just switch.

Investigate injecting connection strings via DI

The idea is that all information needed to run a class is declared via the constructor.

This may seem like excess work and doesn't feel much different than things like Entity framework's configuration defaults.

However, trying to reuse a class outside of the DI setting shows complications. The component cannot be used without configuration that has no explicit ties. Knowledge of the ORM is required to understand why the code doesn't run. Further, configuration via a config file may not always be preferable.

By injecting connection strings, we make this dependency explicit. Within the DI setting, the configuration still happens automagically.

Add automated Seed data sample

public class CreateWithSeedIfNotExists : CreateDatabaseIfNotExists<ApplicationDbContext>
{
    protected override void Seed(ApplicationDbContext context)
    {
        
    }
}

Impact of c# 8 extensions on design

https://adrientorris.github.io/csharp/what-i-get-from-the-preview-of-csharp-8-with-Mads-Torgersen.html#extension_everything
dotnet/csharplang#110

C# will get extensions to instances that can add properties, instance methods, etc.
It may also get Type Classes (like interfaces, but instead of being part of the type definition it is more verified that the class fits the constraint)

What does this mean for my design?

Could I use extension to mimic AOP without dynamic proxies? I.e. extend all types with a log function. These log functions can be maintained separately and different ones can be used based on what log assembly is included? Hmm. This has a hole that I still need funnel info to the logger, which would require to accept the right info to pass on....

Anyway. Questions like that

Too many data contracts?

What is the right balance of data contract boundaries (DPL currently splits them for the DB, accessor, Managers/Engines, and Clients).

This helps bound changes & makes it easier to expose just the needed data, but results in a lot of data conversions and types. Adding a datatype turns into 5+ new files (migrations, data prep, and call chain types).

How can we reduce the burden of added types?

Consider paradigm for random values now that I have bogus

Before I wrote my own random value generators, so I just referenced them on dataPrep from all places. Now, I use bogus inside of dataprep. However, there are still cases where I want to generate random data outside of dataPrep (like object save_update tests). Do I expose Bogus and require all test assemblies to include Bogus, or do I hide bogus behind a custom class?

Consider front-end examples

  • Controller tests
  • javascript tests
  • What framework/pattern should I use? Primarily Asp.net rendering? Angular?
    • Angular would be easier to test in isolation
    • Non-angular js could be a good example of modular js without a framework
    • writing it as a SPA could be a good chance to show modular interface components

Experiment with abstracting Id type with a struct

The major question here is how to map back to the primitive with EF.

This would prevent extremely unpleasant refactoring in case of a need for change in id type. It also would enable some flexibility for multiple id types if necessary.

Try migrating to .NET Core for cross-platform compatibility

Abstract test datastore creation

TestBase and the TestAccessor are both calling Database.EnsureCreated. Instead call to DataPrep, this way we don't even create a datastore is needed and centralize test storage type in one place.

This could also allow us to remove entityframework as a dependency in the test classes

Generative (Statistical) Testing

Are there tools and would it be meaningful to run generated tests against all possible input like in clojure.

The big issue here is understanding what the expected outcome for a set of inputs would be.

Add ReadMe files to explain solution layout and key concepts in each project

Some items to note in readme files

  • link to presentation that spurred this project for key testing infrastructure explanations
  • IDesign structure. Link to ppt or include a ppt to briefly explain.
  • Friend assemblies for hidden internals
  • distributed DI configuration for hidden implementations and less repetition in clients
  • Reason for DBO models and mapping
  • Alternatives and reasoning behind method of integration test reuse
  • Reasoning behind result types
  • reasoning behind solution structure
  • reasoning behind data prep class over direct bogus/autofixture
  • reasoning behind datacontracts
    • contrast data contracts with local-use types (DBOs, presentation objects, engine contracts)

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.