NightOwl888 commented on issue #1017:
URL: https://github.com/apache/lucenenet/issues/1017#issuecomment-2571635427

   Below is the list of features we are missing in the test framework, which is 
up for discussion about whether or not we need these  features. Some I thought 
were clear, but feel free to make a case if you disagree. There are a few 
additional features listed that I think would be useful, but are not 
necessarily required. There are some others that are probably the source of 
some of the bugs we are seeing.
   
   Note that I am listing the features mostly with their Java names. This does 
not mean we have to implement it exactly how it is in Java because while NUnit 
provides a rough approximation of the features that JUnit does, it doesn't 
implement them the same way and does not necessarily provide a 1-to-1 
correlation in terms of how things can be extended. So, even though I am 
listing the TestRule classes, we could ultimately end up with a completely 
different implementation with similar functionality.
   
   Also note that whether or not a feature is required may depend on whether or 
not we implement randomizedtesing (#264). So, that decision could impact this 
feature list a lot.
   
   The goal is to move everything to either Needed or Not Needed and then we 
can open up a GitHub issue for each feature that is Needed.
   
   ## Features: Needed
   
   | 
                  **Feature Name**                  
                | 
                    **Summary**                    
                                                                                
                   | **Notes**                     |
   
|----------------------------------|---------------------------------------------------------------------------------------------------------------------|-------------------------------|
   | Test Rule Chaining (#1088)  | This controls how suite-level and test-level 
rules are nested. It is important that _all_ rules declared in LuceneTestCase 
are executed in proper order if they depend on each other. | The JUnit classes 
should ideally be in the RandomizedTesting namepace, but whether this 
functionality exists internally in Lucene.Net.TestFramework or is made public 
and put into RandomizedTesting will need to be decided. Taking control over 
NUnit to call our chains before everything else and after everything else is a 
considerable challenge and it may not be possible to do it this way without our 
own test adapter. |
   | TestRuleMarkFailure<hr> SuiteFailureMarker |  Suite failure marker (any 
error in the test or suite scope). A rule for marking failed tests and suites. 
| I think we can use NUnit.Framework.Internal.TestResult (which is available 
from TestExecutionContext.CurrentContext .CurrentResult) to get this data from 
NUnit.  |
   | TemporaryFilesCleanupRule <hr> tempDirBase |  Cleans up files after 
running a test. This always runs whether there is an exception or not. | This 
functionality has been implemented as the 
LuceneTestCase.CleanupTemporaryFiles() method, but should be changed if we do 
the Test Rule Chaining.<br><br>NOTE: The tempDirBase is always set to null. 
This seems like a Lucene bug.  |
   | StaticFieldsInvariantRule |  A TestRule that ensures static, reference 
fields of the suite class (and optionally its superclasses) are cleaned up 
after a suite is completed. This is helpful in finding out static memory leaks 
(a class references something huge but is no longer used). | 
StaticFieldsInvariantRule is from randomizedtesting.<br><br>We don't have any 
functionality that cleans up static fields that inherit LuceneTestCase. This 
sounds important to keep memory from leaking.  |
   | NoClassHooksShadowingRule |  Don't allow BeforeClass and AfterClass hook 
shadowing as it is most likely a user error. JUnit rules for shadowed hook 
methods are weird.| NoClassHooksShadowingRule is in 
randomizedtesting.<br><br>This sounds like something we can make a code 
analyzer for so this will fail at design time. It is only required because the 
OneTimeSetUp and OneTimeTearDown methods in Lucene are static and can be 
shadowed. We currently use inheriance, but are considering reverting to the 
original design. See #1087. However, we can probably use a Roslyn code analyzer 
for this so this can be enforced at compile time. Perhaps this could be based 
on a custom attribute to mark methods that should be scanned for this rule. |
   | TestRuleSetupTeardownChained<hr> 
parentChainCallRule<br>parentChainCallRule.setupCalled<br>parentChainCallRule.tearDownCalled
 |  Make sure LuceneTestCase#setUp() and LuceneTestCase#tearDown() were invoked 
even if they have been overriden. We assume nobody will call these out of 
non-overriden methods (they have to be public by contract, unfortunately). The 
top-level methods just set a flag that is checked upon successful execution of 
each test case. | This can be enforced using a code analyzer. It is important 
to do if we don't make these methods static (they are virtual in Lucene). See 
#1087. |
   | TestRuleThreadAndTestName<hr> threadAndTestNameRule<br>IsTestThread | 
Saves the executing thread and method name of the test case. | We can probably 
leave the test name up to NUnit using 
NUnit.Framework.TestContext.CurrentContext .Test.MethodName. But detecting 
whether the calling thread is the same as the test thread is not currently 
implemented. Neither is asserting that it is not null. |
   | TestRuleSetupAndRestoreInstanceEnv |  Prepares and restores LuceneTestCase 
at instance level (fine grained junk that doesn't fit anywhere else). | This 
only sets the BooleanQuery.MaxClauseCount before every test and restores the 
original value when the test is finished. Some tests do this explicitly, but I 
suspect not having it done globally is causing some test conditions to differ 
from Lucene (bugs).  |
   | TestRuleFieldCacheSanity |  This rule will fail the test if it has insane 
field caches. 
([docs](https://lucene.apache.org/core/4_8_0/test-framework/index.html)) | This 
is the only thing that calls LuceneTestCase.AssertSaneFieldCaches(), but it is 
currently not implemented. We should be calling this from the TearDown() method 
(in the right order) or from a rule chain that is setup with the correct 
calling order if we implement rule chaining.  |
   | closeAfterTest() |  Registers a Closeable resource that should be closed 
after the test completes. | It probably makes sense in .NET to make methods for 
both Dispose() and Close(). Dispose() is definitely useful to have. Note this 
was entirely implemented by randomizedtesting (RandomizedContext).<br><br>This 
is not called anywhere by Lucene, it is meant for users. It is probably useful 
and worth having.  |
   | closeAfterSuite()<hr> CloseableDirectory |  Registers a Closeable resource 
that should be closed after the suite (usually class) completes. | It probably 
makes sense in .NET to make methods for both Dispose() and Close(). Dispose() 
is definitely useful to have. Note this was entirely implemented by 
randomizedtesting (RandomizedContext).<br><br>This is called by 
LuceneTestCase.wrapDirectory() in Lucene. We are skipping this call in .NET, 
which is probably leaking resources (maybe even file handles). This may be a 
contributor to the cascade failures we were seeing during testing. We 
definitely need this.  |
   | Compound Random Seed | Test seeds are generated based off of a fixture 
seed. A compound seed combines both seeds into a single string for 
repeatability.  |  This is the approach that is used in randomizedtesting. 
Implementing the random seed this way would make seeds that can be used across 
updates to tests. Currently, if tests are added or removed, it could affect the 
repeatability of the seeds.  |
   | SuppressTempFileChecksAttribute (#898) |   |  Already in progress.  |
   
   ## Features: For Review
   
   | 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Feature&nbsp;Name**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                | 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Summary**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                                                                
                   | **Notes**                     |
   
|----------------------------------|---------------------------------------------------------------------------------------------------------------------|-------------------------------|
   | TestRuleIgnoreAfterMaxFailures <hr> SYSPROP_MAXFAILURES <br> 
SYSPROP_FAILFAST <br> ignoreAfterMaxFailuresDelegate <br> 
ignoreAfterMaxFailures <br> replaceMaxFailureRule() <br> TestRuleDelegate |  
Ignore tests after hitting a designated number of initial failures. This is 
truly a "static" global singleton since it needs to span the lifetime of all 
test classes running inside this JVM (it cannot be part of a class rule). 
<br><br> Optionally skips all of the remaining tests after the first failure. | 
We may be able to utilize the LuceneTestCase.SetUpFixture or 
LuceneTestFrameworkInitializer to manage this with NUnit. |
   | STATIC_LEAK_THRESHOLD <hr> STATIC_LEAK_IGNORED_TYPES |  Max 10mb of static 
data stored in a test suite class after the suite is complete. Prevents static 
data structures leaking and causing OOMs in subsequent tests.<br><br>By-name 
list of ignored types like loggers etc |  |
   | RunListenerPrintReproduceInfo <hr>JENKINS_LARGE_LINE_DOCS_FILE |  A suite 
listener printing a "reproduce string". This ensures test result events are 
always captured properly even if exceptions happen at initialization or suite/ 
hooks level. | RunListenerPrintReproduceInfo is a JUnit run listener. This 
prints similar information that we do during a test failure. However, we should 
review this because there are some things we are not printing out that could be 
helpful. |
   | TestRuleIgnoreTestSuites  |  This rule will cause the suite to be 
assumption-ignored if the test class implements a given marker interface and a 
special property is not set.<br><br>This is a workaround for problems with 
certain JUnit containers (IntelliJ) which automatically discover test suites 
and attempt to run nested classes that we use for testing the test framework 
itself. |  |
   | NoInstanceHooksOverridesRule |  Don't allow Before and After hook 
overrides as it is most likely a user error and will result in superclass 
methods not being called (requires manual chaining).  | 
NoInstanceHooksOverridesRule is in randomizedtesting<br><br>If we implement 
nested attributes with the same name as NUnit, we can largely avoid this. See 
#1087. If we need this, I think this would be best enforced using a Roslyn code 
analyzer (build failure) rather than runtime checks. |
   | FailureMarker<hr> WithNestedTests |  A JUnit RunListener that detects 
suite/test failures. Lucene needs it because failures due to thread leaks 
happen outside of any rule contexts.<hr>An abstract test class that prepares 
nested test classes to run. A nested test class will assume it's executed under 
control of this class and be ignored otherwise. <br><br>The purpose of this is 
so that nested test suites don't run from IDEs like Eclipse (where they are 
automatically detected).  |   |
   | BadAppleAttribute |  Attribute for tests that fail frequently and should 
be moved to a <a 
href="https://builds.apache.org/job/Lucene-BadApples-trunk-java7/";>"vault" plan 
in Jenkins</a>. | Being that we have AwaitsFixAttribute, this seems like 
redundant functionality (unless these were never intended to be fixed). Maybe 
there is a use case for it, though.  |
   
   ## Features: For Review (Not in Lucene)
   
   | 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Feature&nbsp;Name**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                | 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Summary**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                                                                
                   | **Notes**                     |
   
|----------------------------------|---------------------------------------------------------------------------------------------------------------------|-------------------------------|
   | RandomizedTesting (#264) |  Dependency of Lucene test-framework that 
extends JUnit. |  There may be some compelling reasons for implementing this. 
See:  https://chatgpt.com/share/677a832d-3424-8005-97d7-1c024c68302d |
   | Portable Random Seeds |  Random seeds that produce the same result in both 
.NET and Java. |  This would be very useful for debugging if we can achieve it. 
However, the benefit may not be worth the cost of pulling it off. |
   | Enforce Custom Asserts | Provide build warnings for using NUnit asserts 
due to performance problems.  |  Our `Assert` class performs much better for 
collections and numeric types than NUnit does. Enforcing its usage using a 
Roslyn code analyzer would save us work of having to hunt down violations 
manually. This would be useful whether or not we finish #306, but it would be 
better if we finished that task first (or even consider moving it over to 
RandomizedTesting or another package). |
   | Disallow using NUnit TestFixtureAttribute | Enforce the use of the custom 
TestFixtureAttribute when subclassing LuceneTestCase | Using NUnit's 
TestFixtureAttribute will bypass some of the test framework setup, which will 
affect repeatability of random tests and probably cause other problems. Users 
should get build failures if they attempt this. They are free to use it on 
classes that do not extend LuceneTestCase, though.  |
   | Disallow using NUnit OneTimeSetUpAttribute and OneTimeTearDownAttribute | 
Enforce the use of the custom OneTimeSetUpAttribute  and 
OneTimeTearDownAttribute when subclassing LuceneTestCase | Using NUnit's 
OneTimeSetUpAttribute  or OneTimeTearDownAttribute will cause setup problems 
with the test framework because NUnit could call the user's class first. Users 
should get build failures if they attempt this. They are free to use it on 
classes that do not extend LuceneTestCase, though. This depends on #1087.  |
   
   
   ## Features: Not Needed
   
   | 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Feature&nbsp;Name**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                | 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**Summary**&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                                                                
                   | **Notes**                     |
   
|----------------------------------|---------------------------------------------------------------------------------------------------------------------|-------------------------------|
   | SystemPropertiesInvariantRule <hr> STATIC_LEAK_IGNORED_TYPES |  These 
property keys will be ignored in verification of altered properties.<br><br>A 
TestRule that ensures system properties remain unmodified by the nested 
Statement. This can be applied both at suite level and at test 
level.<br><br>This rule requires appropriate security permission to read and 
write system properties System#getProperties() if running under a security 
manager. | SystemPropertiesInvariantRule is in randomizedtesting.<br><br>The 
values are { "user.timezone", "java.rmi.server.randomIDs" }, so this doesn't 
appear very useful in .NET since we don't have BCL system properties and time 
zone is not something that can be set on a given thread. Also, our system 
properties are readonly inside of the application (we only provide a default 
value if the system property is not supplied on the outside of the 
application), so there is no danger of a user overwriting them at runtime.  |
   | TestRuleStoreClassName<hr> ClassNameRule |  Stores the suite name so you 
can retrieve it from getTestClass() | I don't think this is needed because 
NUnit tracks the name of the test class and keeps it in scope already.  |
   | TestRuleAssertionsRequired |  Verifies that the caller passed the system 
property to enable assertions. | Being that the default setting when the test 
framework is engaged is true and we also fixed the tests so it is possible to 
run them (skipping some) with asserts disabled, we don't need this unless it is 
required by randomizedtesting for some reason. It is unlikely many users of the 
test framework will even be aware of this feature.  |
   | LuceneJUnit3MethodProvider |  Backwards compatible test* method provider 
(public, non-static). | This is a helper class to provide JUnit3 naming 
functionality to later versions of JUnit to scan for tests (by name, not by 
attribute). Java-specific. Not needed.  |
   | QuickPatchThreadsFilter |  Last minute patches. TODO: remove when 
integrated in system filters in rr. | This appears to be Java-specific and 
temporary. It was only used by SOLR. We don't need this. |
   | RemoveUponClose |  A Closeable that attempts to remove a given 
file/folder. | This removes a specific file, but only if the test was 
successful. Not sure what the point is. There are no references and it is 
internal. We don't need it. |
   | Rethrow |  Sneaky: rethrowing checked exceptions as unchecked ones. Eh, it 
is sometimes useful...<br><br>Pulled from <a 
href="http://www.javapuzzlers.com";>Java Puzzlers</a>. see 
"http://www.amazon.com/Java-Puzzlers-Traps-Pitfalls-Corner/dp/032133678X"; | 
This only applies to Java because in .NET we don't have checked exceptions. We 
don't need it. In all cases we can remove the try/catch altogether. |
   | TestSecurityManager |  A SecurityManager that prevents tests calling 
System#exit(int). Only the test runner itself is allowed to exit the 
JVM.<br><br>Use this with -Djava.security.manager= 
org.apache.lucene.util.TestSecurityManager. | We don't need this because we 
don't have our own custom test runner. Given that a stand alone console app to 
run tests is not likely something that will ever exist even if we do implement 
randomizedtesting, we probably don't need it. |


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@lucenenet.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to