Many of our system tests are written in the BDD style, and we make worthy use of inherited behaviors to minimize duplication, for example, it can be a basic hierarchy for buy tests.
class BehavesLikeSuccessfulPurchase
class BehavesLikePurchaseWithValidCreditCard : BehavesLikeSuccessfulPurchase
In this case, it BehavesLikeSuccessfulPurchasedefines general behaviors, such as an account operator, must have a debit record, and the class BehavesLikePurchaseWithValidCreditCarddefines a test workflow for buying any type of product with a valid credit card, so the tests are small, which simply supply a specific product instance, for example
[Concern(typeof(Video))]
class WhenPurchasedWithValidCreditCard : BehavesLikePurchaseWithValidCreditCard
However, depending on the specific type of product, we also need to have some additional checks, for example, whenever a video is successfully purchased, we want to check that it is added to the userβs video library. Ideally, this can be defined by another class and mixed using a hypothetical syntax:
class BehavesLikeSuccessfulVideoPurchase
[Concern(typeof(Video))]
class WhenPurchasedWithValidCreditCard : BehavesLikePurchaseWithValidCreditCard
mixin BehavesLikeSuccessfulVideoPurchase
{
}
But, of course, C # does not support multiple inheritance or mixes, so we end up writing down the load of boiler plate methods, which forwards calls to additional behaviors that must change every time the behavior changes.
, , () , . xUnit , , , , - ?